Home | History | Annotate | Download | only in trees
      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/trees/layer_tree_host.h"
      6 
      7 #include "base/basictypes.h"
      8 #include "cc/layers/content_layer.h"
      9 #include "cc/layers/heads_up_display_layer.h"
     10 #include "cc/layers/io_surface_layer.h"
     11 #include "cc/layers/layer_impl.h"
     12 #include "cc/layers/picture_layer.h"
     13 #include "cc/layers/scrollbar_layer.h"
     14 #include "cc/layers/texture_layer.h"
     15 #include "cc/layers/texture_layer_impl.h"
     16 #include "cc/layers/video_layer.h"
     17 #include "cc/layers/video_layer_impl.h"
     18 #include "cc/output/filter_operations.h"
     19 #include "cc/test/fake_content_layer.h"
     20 #include "cc/test/fake_content_layer_client.h"
     21 #include "cc/test/fake_content_layer_impl.h"
     22 #include "cc/test/fake_context_provider.h"
     23 #include "cc/test/fake_delegated_renderer_layer.h"
     24 #include "cc/test/fake_delegated_renderer_layer_impl.h"
     25 #include "cc/test/fake_layer_tree_host_client.h"
     26 #include "cc/test/fake_output_surface.h"
     27 #include "cc/test/fake_scoped_ui_resource.h"
     28 #include "cc/test/fake_scrollbar.h"
     29 #include "cc/test/fake_scrollbar_layer.h"
     30 #include "cc/test/fake_video_frame_provider.h"
     31 #include "cc/test/layer_tree_test.h"
     32 #include "cc/test/render_pass_test_common.h"
     33 #include "cc/test/test_web_graphics_context_3d.h"
     34 #include "cc/trees/layer_tree_host_impl.h"
     35 #include "cc/trees/layer_tree_impl.h"
     36 #include "cc/trees/single_thread_proxy.h"
     37 #include "gpu/GLES2/gl2extchromium.h"
     38 #include "media/base/media.h"
     39 
     40 using media::VideoFrame;
     41 using WebKit::WebGraphicsContext3D;
     42 
     43 namespace cc {
     44 namespace {
     45 
     46 // These tests deal with losing the 3d graphics context.
     47 class LayerTreeHostContextTest : public LayerTreeTest {
     48  public:
     49   LayerTreeHostContextTest()
     50       : LayerTreeTest(),
     51         context3d_(NULL),
     52         times_to_fail_create_(0),
     53         times_to_fail_initialize_(0),
     54         times_to_lose_on_create_(0),
     55         times_to_lose_during_commit_(0),
     56         times_to_lose_during_draw_(0),
     57         times_to_fail_recreate_(0),
     58         times_to_fail_reinitialize_(0),
     59         times_to_lose_on_recreate_(0),
     60         times_to_fail_create_offscreen_(0),
     61         times_to_fail_recreate_offscreen_(0),
     62         times_to_expect_create_failed_(0),
     63         times_create_failed_(0),
     64         times_offscreen_created_(0),
     65         committed_at_least_once_(false),
     66         context_should_support_io_surface_(false),
     67         fallback_context_works_(false) {
     68     media::InitializeMediaLibraryForTesting();
     69   }
     70 
     71   void LoseContext() {
     72     context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
     73                                     GL_INNOCENT_CONTEXT_RESET_ARB);
     74     context3d_ = NULL;
     75   }
     76 
     77   virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
     78     return TestWebGraphicsContext3D::Create();
     79   }
     80 
     81   virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
     82       OVERRIDE {
     83     if (times_to_fail_create_) {
     84       --times_to_fail_create_;
     85       ExpectCreateToFail();
     86       return scoped_ptr<OutputSurface>();
     87     }
     88 
     89     scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
     90     context3d_ = context3d.get();
     91 
     92     if (context_should_support_io_surface_) {
     93       context3d_->set_have_extension_io_surface(true);
     94       context3d_->set_have_extension_egl_image(true);
     95     }
     96 
     97     if (times_to_fail_initialize_ && !(fallback && fallback_context_works_)) {
     98       --times_to_fail_initialize_;
     99       // Make the context get lost during reinitialization.
    100       // The number of times MakeCurrent succeeds is not important, and
    101       // can be changed if needed to make this pass with future changes.
    102       context3d_->set_times_make_current_succeeds(2);
    103       ExpectCreateToFail();
    104     } else if (times_to_lose_on_create_) {
    105       --times_to_lose_on_create_;
    106       LoseContext();
    107       ExpectCreateToFail();
    108     }
    109 
    110     if (delegating_renderer()) {
    111       return FakeOutputSurface::CreateDelegating3d(
    112           context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>();
    113     }
    114     return FakeOutputSurface::Create3d(
    115         context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>();
    116   }
    117 
    118   scoped_ptr<TestWebGraphicsContext3D> CreateOffscreenContext3d() {
    119     if (!context3d_)
    120       return scoped_ptr<TestWebGraphicsContext3D>();
    121 
    122     ++times_offscreen_created_;
    123 
    124     if (times_to_fail_create_offscreen_) {
    125       --times_to_fail_create_offscreen_;
    126       ExpectCreateToFail();
    127       return scoped_ptr<TestWebGraphicsContext3D>();
    128     }
    129 
    130     scoped_ptr<TestWebGraphicsContext3D> offscreen_context3d =
    131         TestWebGraphicsContext3D::Create().Pass();
    132     DCHECK(offscreen_context3d);
    133     context3d_->add_share_group_context(offscreen_context3d.get());
    134 
    135     return offscreen_context3d.Pass();
    136   }
    137 
    138   virtual scoped_refptr<cc::ContextProvider>
    139   OffscreenContextProviderForMainThread() OVERRIDE {
    140     DCHECK(!HasImplThread());
    141 
    142     if (!offscreen_contexts_main_thread_.get() ||
    143         offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
    144       offscreen_contexts_main_thread_ = FakeContextProvider::Create(
    145           base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
    146                      base::Unretained(this)));
    147       if (offscreen_contexts_main_thread_.get() &&
    148           !offscreen_contexts_main_thread_->BindToCurrentThread())
    149         offscreen_contexts_main_thread_ = NULL;
    150     }
    151     return offscreen_contexts_main_thread_;
    152   }
    153 
    154   virtual scoped_refptr<cc::ContextProvider>
    155   OffscreenContextProviderForCompositorThread() OVERRIDE {
    156     DCHECK(HasImplThread());
    157 
    158     if (!offscreen_contexts_compositor_thread_.get() ||
    159         offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
    160       offscreen_contexts_compositor_thread_ = FakeContextProvider::Create(
    161           base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
    162                      base::Unretained(this)));
    163     }
    164     return offscreen_contexts_compositor_thread_;
    165   }
    166 
    167   virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
    168                                      LayerTreeHostImpl::FrameData* frame,
    169                                      bool result) OVERRIDE {
    170     EXPECT_TRUE(result);
    171     if (!times_to_lose_during_draw_)
    172       return result;
    173 
    174     --times_to_lose_during_draw_;
    175     context3d_->set_times_make_current_succeeds(0);
    176 
    177     times_to_fail_create_ = times_to_fail_recreate_;
    178     times_to_fail_recreate_ = 0;
    179     times_to_fail_initialize_ = times_to_fail_reinitialize_;
    180     times_to_fail_reinitialize_ = 0;
    181     times_to_lose_on_create_ = times_to_lose_on_recreate_;
    182     times_to_lose_on_recreate_ = 0;
    183     times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
    184     times_to_fail_recreate_offscreen_ = 0;
    185 
    186     return result;
    187   }
    188 
    189   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
    190     committed_at_least_once_ = true;
    191 
    192     if (!times_to_lose_during_commit_)
    193       return;
    194     --times_to_lose_during_commit_;
    195     LoseContext();
    196 
    197     times_to_fail_create_ = times_to_fail_recreate_;
    198     times_to_fail_recreate_ = 0;
    199     times_to_fail_initialize_ = times_to_fail_reinitialize_;
    200     times_to_fail_reinitialize_ = 0;
    201     times_to_lose_on_create_ = times_to_lose_on_recreate_;
    202     times_to_lose_on_recreate_ = 0;
    203     times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
    204     times_to_fail_recreate_offscreen_ = 0;
    205   }
    206 
    207   virtual void DidFailToInitializeOutputSurface() OVERRIDE {
    208     ++times_create_failed_;
    209   }
    210 
    211   virtual void TearDown() OVERRIDE {
    212     LayerTreeTest::TearDown();
    213     EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
    214   }
    215 
    216   void ExpectCreateToFail() {
    217     ++times_to_expect_create_failed_;
    218   }
    219 
    220  protected:
    221   TestWebGraphicsContext3D* context3d_;
    222   int times_to_fail_create_;
    223   int times_to_fail_initialize_;
    224   int times_to_lose_on_create_;
    225   int times_to_lose_during_commit_;
    226   int times_to_lose_during_draw_;
    227   int times_to_fail_recreate_;
    228   int times_to_fail_reinitialize_;
    229   int times_to_lose_on_recreate_;
    230   int times_to_fail_create_offscreen_;
    231   int times_to_fail_recreate_offscreen_;
    232   int times_to_expect_create_failed_;
    233   int times_create_failed_;
    234   int times_offscreen_created_;
    235   bool committed_at_least_once_;
    236   bool context_should_support_io_surface_;
    237   bool fallback_context_works_;
    238 
    239   scoped_refptr<FakeContextProvider> offscreen_contexts_main_thread_;
    240   scoped_refptr<FakeContextProvider> offscreen_contexts_compositor_thread_;
    241 };
    242 
    243 class LayerTreeHostContextTestLostContextSucceeds
    244     : public LayerTreeHostContextTest {
    245  public:
    246   LayerTreeHostContextTestLostContextSucceeds()
    247       : LayerTreeHostContextTest(),
    248         test_case_(0),
    249         num_losses_(0),
    250         recovered_context_(true),
    251         first_initialized_(false) {}
    252 
    253   virtual void BeginTest() OVERRIDE {
    254     PostSetNeedsCommitToMainThread();
    255   }
    256 
    257   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
    258     EXPECT_TRUE(succeeded);
    259 
    260     if (first_initialized_)
    261       ++num_losses_;
    262     else
    263       first_initialized_ = true;
    264 
    265     recovered_context_ = true;
    266   }
    267 
    268   virtual void AfterTest() OVERRIDE {
    269     EXPECT_EQ(11u, test_case_);
    270     EXPECT_EQ(8 + 10 + 10 + 1, num_losses_);
    271   }
    272 
    273   virtual void DidCommitAndDrawFrame() OVERRIDE {
    274     // If the last frame had a context loss, then we'll commit again to
    275     // recover.
    276     if (!recovered_context_)
    277       return;
    278     if (times_to_lose_during_commit_)
    279       return;
    280     if (times_to_lose_during_draw_)
    281       return;
    282 
    283     recovered_context_ = false;
    284     if (NextTestCase())
    285       InvalidateAndSetNeedsCommit();
    286     else
    287       EndTest();
    288   }
    289 
    290   virtual void InvalidateAndSetNeedsCommit() {
    291     // Cause damage so we try to draw.
    292     layer_tree_host()->root_layer()->SetNeedsDisplay();
    293     layer_tree_host()->SetNeedsCommit();
    294   }
    295 
    296   bool NextTestCase() {
    297     static const TestCase kTests[] = {
    298       // Losing the context and failing to recreate it (or losing it again
    299       // immediately) a small number of times should succeed.
    300       { 1,      // times_to_lose_during_commit
    301         0,      // times_to_lose_during_draw
    302         3,      // times_to_fail_reinitialize
    303         0,      // times_to_fail_recreate
    304         0,      // times_to_lose_on_recreate
    305         0,      // times_to_fail_recreate_offscreen
    306         false,  // fallback_context_works
    307     },
    308       { 0,      // times_to_lose_during_commit
    309         1,      // times_to_lose_during_draw
    310         3,      // times_to_fail_reinitialize
    311         0,      // times_to_fail_recreate
    312         0,      // times_to_lose_on_recreate
    313         0,      // times_to_fail_recreate_offscreen
    314         false,  // fallback_context_works
    315     },
    316       { 1,      // times_to_lose_during_commit
    317         0,      // times_to_lose_during_draw
    318         0,      // times_to_fail_reinitialize
    319         3,      // times_to_fail_recreate
    320         0,      // times_to_lose_on_recreate
    321         0,      // times_to_fail_recreate_offscreen
    322         false,  // fallback_context_works
    323     },
    324       { 0,      // times_to_lose_during_commit
    325         1,      // times_to_lose_during_draw
    326         0,      // times_to_fail_reinitialize
    327         3,      // times_to_fail_recreate
    328         0,      // times_to_lose_on_recreate
    329         0,      // times_to_fail_recreate_offscreen
    330         false,  // fallback_context_works
    331     },
    332       { 1,      // times_to_lose_during_commit
    333         0,      // times_to_lose_during_draw
    334         0,      // times_to_fail_reinitialize
    335         0,      // times_to_fail_recreate
    336         3,      // times_to_lose_on_recreate
    337         0,      // times_to_fail_recreate_offscreen
    338         false,  // fallback_context_works
    339     },
    340       { 0,      // times_to_lose_during_commit
    341         1,      // times_to_lose_during_draw
    342         0,      // times_to_fail_reinitialize
    343         0,      // times_to_fail_recreate
    344         3,      // times_to_lose_on_recreate
    345         0,      // times_to_fail_recreate_offscreen
    346         false,  // fallback_context_works
    347     },
    348       { 1,      // times_to_lose_during_commit
    349         0,      // times_to_lose_during_draw
    350         0,      // times_to_fail_reinitialize
    351         0,      // times_to_fail_recreate
    352         0,      // times_to_lose_on_recreate
    353         3,      // times_to_fail_recreate_offscreen
    354         false,  // fallback_context_works
    355     },
    356       { 0,      // times_to_lose_during_commit
    357         1,      // times_to_lose_during_draw
    358         0,      // times_to_fail_reinitialize
    359         0,      // times_to_fail_recreate
    360         0,      // times_to_lose_on_recreate
    361         3,      // times_to_fail_recreate_offscreen
    362         false,  // fallback_context_works
    363     },
    364              // Losing the context and recreating it any number of times should
    365       // succeed.
    366       { 10,  // times_to_lose_during_commit
    367         0,   // times_to_lose_during_draw
    368         0,   // times_to_fail_reinitialize
    369         0,   // times_to_fail_recreate
    370         0,   // times_to_lose_on_recreate
    371         0,   // times_to_fail_recreate_offscreen
    372         false,  // fallback_context_works
    373     },
    374       { 0,      // times_to_lose_during_commit
    375         10,     // times_to_lose_during_draw
    376         0,      // times_to_fail_reinitialize
    377         0,      // times_to_fail_recreate
    378         0,      // times_to_lose_on_recreate
    379         0,      // times_to_fail_recreate_offscreen
    380         false,  // fallback_context_works
    381     },
    382       // Losing the context, failing to reinitialize it, and making a fallback
    383       // context should work.
    384       { 0,      // times_to_lose_during_commit
    385         1,      // times_to_lose_during_draw
    386         10,     // times_to_fail_reinitialize
    387         0,      // times_to_fail_recreate
    388         0,      // times_to_lose_on_recreate
    389         0,      // times_to_fail_recreate_offscreen
    390         true,   // fallback_context_works
    391     },
    392     };
    393 
    394     if (test_case_ >= arraysize(kTests))
    395       return false;
    396 
    397     times_to_lose_during_commit_ =
    398         kTests[test_case_].times_to_lose_during_commit;
    399     times_to_lose_during_draw_ =
    400         kTests[test_case_].times_to_lose_during_draw;
    401     times_to_fail_reinitialize_ = kTests[test_case_].times_to_fail_reinitialize;
    402     times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
    403     times_to_lose_on_recreate_ = kTests[test_case_].times_to_lose_on_recreate;
    404     times_to_fail_recreate_offscreen_ =
    405         kTests[test_case_].times_to_fail_recreate_offscreen;
    406     fallback_context_works_ = kTests[test_case_].fallback_context_works;
    407     ++test_case_;
    408     return true;
    409   }
    410 
    411   struct TestCase {
    412     int times_to_lose_during_commit;
    413     int times_to_lose_during_draw;
    414     int times_to_fail_reinitialize;
    415     int times_to_fail_recreate;
    416     int times_to_lose_on_recreate;
    417     int times_to_fail_recreate_offscreen;
    418     bool fallback_context_works;
    419   };
    420 
    421  protected:
    422   size_t test_case_;
    423   int num_losses_;
    424   bool recovered_context_;
    425   bool first_initialized_;
    426 };
    427 
    428 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
    429 
    430 class LayerTreeHostContextTestLostContextSucceedsWithContent
    431     : public LayerTreeHostContextTestLostContextSucceeds {
    432  public:
    433   LayerTreeHostContextTestLostContextSucceedsWithContent()
    434       : LayerTreeHostContextTestLostContextSucceeds() {}
    435 
    436   virtual void SetupTree() OVERRIDE {
    437     root_ = Layer::Create();
    438     root_->SetBounds(gfx::Size(10, 10));
    439     root_->SetAnchorPoint(gfx::PointF());
    440     root_->SetIsDrawable(true);
    441 
    442     content_ = FakeContentLayer::Create(&client_);
    443     content_->SetBounds(gfx::Size(10, 10));
    444     content_->SetAnchorPoint(gfx::PointF());
    445     content_->SetIsDrawable(true);
    446     if (use_surface_) {
    447       content_->SetForceRenderSurface(true);
    448       // Filters require us to create an offscreen context.
    449       FilterOperations filters;
    450       filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
    451       content_->SetFilters(filters);
    452       content_->SetBackgroundFilters(filters);
    453     }
    454 
    455     root_->AddChild(content_);
    456 
    457     layer_tree_host()->SetRootLayer(root_);
    458     LayerTreeHostContextTest::SetupTree();
    459   }
    460 
    461   virtual void InvalidateAndSetNeedsCommit() OVERRIDE {
    462     // Invalidate the render surface so we don't try to use a cached copy of the
    463     // surface.  We want to make sure to test the drawing paths for drawing to
    464     // a child surface.
    465     content_->SetNeedsDisplay();
    466     LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
    467   }
    468 
    469   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
    470     FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>(
    471         host_impl->active_tree()->root_layer()->children()[0]);
    472     // Even though the context was lost, we should have a resource. The
    473     // TestWebGraphicsContext3D ensures that this resource is created with
    474     // the active context.
    475     EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
    476 
    477     cc::ContextProvider* contexts =
    478         host_impl->resource_provider()->offscreen_context_provider();
    479     if (use_surface_) {
    480       EXPECT_TRUE(contexts->Context3d());
    481       // TODO(danakj): Make a fake GrContext.
    482       // EXPECT_TRUE(contexts->GrContext());
    483     } else {
    484       EXPECT_FALSE(contexts);
    485     }
    486   }
    487 
    488   virtual void AfterTest() OVERRIDE {
    489     LayerTreeHostContextTestLostContextSucceeds::AfterTest();
    490     if (use_surface_) {
    491       // 1 create to start with +
    492       // 6 from test cases that fail on initializing the renderer (after the
    493       // offscreen context is created) +
    494       // 6 from test cases that lose the offscreen context directly +
    495       // 4 from test cases that create a fallback +
    496       // All the test cases that recreate both contexts only once
    497       // per time it is lost.
    498       EXPECT_EQ(6 + 6 + 1 + 4 + num_losses_, times_offscreen_created_);
    499     } else {
    500       EXPECT_EQ(0, times_offscreen_created_);
    501     }
    502   }
    503 
    504  protected:
    505   bool use_surface_;
    506   FakeContentLayerClient client_;
    507   scoped_refptr<Layer> root_;
    508   scoped_refptr<ContentLayer> content_;
    509 };
    510 
    511 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    512        NoSurface_SingleThread_DirectRenderer) {
    513   use_surface_ = false;
    514   RunTest(false, false, false);
    515 }
    516 
    517 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    518        NoSurface_SingleThread_DelegatingRenderer) {
    519   use_surface_ = false;
    520   RunTest(false, true, false);
    521 }
    522 
    523 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    524        NoSurface_MultiThread_DirectRenderer_MainThreadPaint) {
    525   use_surface_ = false;
    526   RunTest(true, false, false);
    527 }
    528 
    529 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    530        NoSurface_MultiThread_DirectRenderer_ImplSidePaint) {
    531   use_surface_ = false;
    532   RunTest(true, false, true);
    533 }
    534 
    535 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    536        NoSurface_MultiThread_DelegatingRenderer_MainThreadPaint) {
    537   use_surface_ = false;
    538   RunTest(true, true, false);
    539 }
    540 
    541 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    542        NoSurface_MultiThread_DelegatingRenderer_ImplSidePaint) {
    543   use_surface_ = false;
    544   RunTest(true, true, true);
    545 }
    546 
    547 // Surfaces don't exist with a delegating renderer.
    548 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    549        WithSurface_SingleThread_DirectRenderer) {
    550   use_surface_ = true;
    551   RunTest(false, false, false);
    552 }
    553 
    554 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    555        WithSurface_MultiThread_DirectRenderer_MainThreadPaint) {
    556   use_surface_ = true;
    557   RunTest(true, false, false);
    558 }
    559 
    560 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
    561        WithSurface_MultiThread_DirectRenderer_ImplSidePaint) {
    562   use_surface_ = true;
    563   RunTest(true, false, true);
    564 }
    565 
    566 class LayerTreeHostContextTestOffscreenContextFails
    567     : public LayerTreeHostContextTest {
    568  public:
    569   virtual void SetupTree() OVERRIDE {
    570     root_ = Layer::Create();
    571     root_->SetBounds(gfx::Size(10, 10));
    572     root_->SetAnchorPoint(gfx::PointF());
    573     root_->SetIsDrawable(true);
    574 
    575     content_ = FakeContentLayer::Create(&client_);
    576     content_->SetBounds(gfx::Size(10, 10));
    577     content_->SetAnchorPoint(gfx::PointF());
    578     content_->SetIsDrawable(true);
    579     content_->SetForceRenderSurface(true);
    580     // Filters require us to create an offscreen context.
    581     FilterOperations filters;
    582     filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
    583     content_->SetFilters(filters);
    584     content_->SetBackgroundFilters(filters);
    585 
    586     root_->AddChild(content_);
    587 
    588     layer_tree_host()->SetRootLayer(root_);
    589     LayerTreeHostContextTest::SetupTree();
    590   }
    591 
    592   virtual void BeginTest() OVERRIDE {
    593     times_to_fail_create_offscreen_ = 1;
    594     PostSetNeedsCommitToMainThread();
    595   }
    596 
    597   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
    598     cc::ContextProvider* contexts =
    599         host_impl->resource_provider()->offscreen_context_provider();
    600     EXPECT_FALSE(contexts);
    601 
    602     // This did not lead to create failure.
    603     times_to_expect_create_failed_ = 0;
    604     EndTest();
    605   }
    606 
    607   virtual void AfterTest() OVERRIDE {}
    608 
    609  protected:
    610   FakeContentLayerClient client_;
    611   scoped_refptr<Layer> root_;
    612   scoped_refptr<ContentLayer> content_;
    613 };
    614 
    615 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestOffscreenContextFails);
    616 
    617 class LayerTreeHostContextTestLostContextFails
    618     : public LayerTreeHostContextTest {
    619  public:
    620   LayerTreeHostContextTestLostContextFails()
    621       : LayerTreeHostContextTest(),
    622         num_commits_(0),
    623         first_initialized_(false) {
    624     times_to_lose_during_commit_ = 1;
    625   }
    626 
    627   virtual void BeginTest() OVERRIDE {
    628     PostSetNeedsCommitToMainThread();
    629   }
    630 
    631   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
    632     if (first_initialized_) {
    633       EXPECT_FALSE(succeeded);
    634       EndTest();
    635     } else {
    636       first_initialized_ = true;
    637     }
    638   }
    639 
    640   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
    641     LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
    642 
    643     ++num_commits_;
    644     if (num_commits_ == 1) {
    645       // When the context is ok, we should have these things.
    646       EXPECT_TRUE(host_impl->output_surface());
    647       EXPECT_TRUE(host_impl->renderer());
    648       EXPECT_TRUE(host_impl->resource_provider());
    649       return;
    650     }
    651 
    652     // When context recreation fails we shouldn't be left with any of them.
    653     EXPECT_FALSE(host_impl->output_surface());
    654     EXPECT_FALSE(host_impl->renderer());
    655     EXPECT_FALSE(host_impl->resource_provider());
    656   }
    657 
    658   virtual void AfterTest() OVERRIDE {}
    659 
    660  private:
    661   int num_commits_;
    662   bool first_initialized_;
    663 };
    664 
    665 TEST_F(LayerTreeHostContextTestLostContextFails,
    666        FailReinitialize100_SingleThread_DirectRenderer) {
    667   times_to_fail_reinitialize_ = 100;
    668   times_to_fail_recreate_ = 0;
    669   times_to_lose_on_recreate_ = 0;
    670   RunTest(false, false, false);
    671 }
    672 
    673 TEST_F(LayerTreeHostContextTestLostContextFails,
    674        FailReinitialize100_SingleThread_DelegatingRenderer) {
    675   times_to_fail_reinitialize_ = 100;
    676   times_to_fail_recreate_ = 0;
    677   times_to_lose_on_recreate_ = 0;
    678   RunTest(false, true, false);
    679 }
    680 
    681 TEST_F(LayerTreeHostContextTestLostContextFails,
    682        FailReinitialize100_MultiThread_DirectRenderer_MainThreadPaint) {
    683   times_to_fail_reinitialize_ = 100;
    684   times_to_fail_recreate_ = 0;
    685   times_to_lose_on_recreate_ = 0;
    686   RunTest(true, false, false);
    687 }
    688 
    689 TEST_F(LayerTreeHostContextTestLostContextFails,
    690        FailReinitialize100_MultiThread_DirectRenderer_ImplSidePaint) {
    691   times_to_fail_reinitialize_ = 100;
    692   times_to_fail_recreate_ = 0;
    693   times_to_lose_on_recreate_ = 0;
    694   RunTest(true, false, true);
    695 }
    696 
    697 TEST_F(LayerTreeHostContextTestLostContextFails,
    698        FailReinitialize100_MultiThread_DelegatingRenderer_MainThreadPaint) {
    699   times_to_fail_reinitialize_ = 100;
    700   times_to_fail_recreate_ = 0;
    701   times_to_lose_on_recreate_ = 0;
    702   RunTest(true, true, false);
    703 }
    704 
    705 TEST_F(LayerTreeHostContextTestLostContextFails,
    706        FailReinitialize100_MultiThread_DelegatingRenderer_ImplSidePaint) {
    707   times_to_fail_reinitialize_ = 100;
    708   times_to_fail_recreate_ = 0;
    709   times_to_lose_on_recreate_ = 0;
    710   RunTest(true, true, true);
    711 }
    712 
    713 TEST_F(LayerTreeHostContextTestLostContextFails,
    714        FailRecreate100_SingleThread_DirectRenderer) {
    715   times_to_fail_reinitialize_ = 0;
    716   times_to_fail_recreate_ = 100;
    717   times_to_lose_on_recreate_ = 0;
    718   RunTest(false, false, false);
    719 }
    720 
    721 TEST_F(LayerTreeHostContextTestLostContextFails,
    722        FailRecreate100_SingleThread_DelegatingRenderer) {
    723   times_to_fail_reinitialize_ = 0;
    724   times_to_fail_recreate_ = 100;
    725   times_to_lose_on_recreate_ = 0;
    726   RunTest(false, true, false);
    727 }
    728 
    729 TEST_F(LayerTreeHostContextTestLostContextFails,
    730        FailRecreate100_MultiThread_DirectRenderer_MainThreadPaint) {
    731   times_to_fail_reinitialize_ = 0;
    732   times_to_fail_recreate_ = 100;
    733   times_to_lose_on_recreate_ = 0;
    734   RunTest(true, false, false);
    735 }
    736 
    737 TEST_F(LayerTreeHostContextTestLostContextFails,
    738        FailRecreate100_MultiThread_DirectRenderer_ImplSidePaint) {
    739   times_to_fail_reinitialize_ = 0;
    740   times_to_fail_recreate_ = 100;
    741   times_to_lose_on_recreate_ = 0;
    742   RunTest(true, false, true);
    743 }
    744 
    745 TEST_F(LayerTreeHostContextTestLostContextFails,
    746        FailRecreate100_MultiThread_DelegatingRenderer_MainThreadPaint) {
    747   times_to_fail_reinitialize_ = 0;
    748   times_to_fail_recreate_ = 100;
    749   times_to_lose_on_recreate_ = 0;
    750   RunTest(true, true, false);
    751 }
    752 
    753 TEST_F(LayerTreeHostContextTestLostContextFails,
    754        FailRecreate100_MultiThread_DelegatingRenderer_ImplSidePaint) {
    755   times_to_fail_reinitialize_ = 0;
    756   times_to_fail_recreate_ = 100;
    757   times_to_lose_on_recreate_ = 0;
    758   RunTest(true, true, true);
    759 }
    760 
    761 TEST_F(LayerTreeHostContextTestLostContextFails,
    762        LoseOnRecreate100_SingleThread_DirectRenderer) {
    763   times_to_fail_reinitialize_ = 0;
    764   times_to_fail_recreate_ = 0;
    765   times_to_lose_on_recreate_ = 100;
    766   RunTest(false, false, false);
    767 }
    768 
    769 TEST_F(LayerTreeHostContextTestLostContextFails,
    770        LoseOnRecreate100_SingleThread_DelegatingRenderer) {
    771   times_to_fail_reinitialize_ = 0;
    772   times_to_fail_recreate_ = 0;
    773   times_to_lose_on_recreate_ = 100;
    774   RunTest(false, true, false);
    775 }
    776 
    777 TEST_F(LayerTreeHostContextTestLostContextFails,
    778        LoseOnRecreate100_MultiThread_DirectRenderer_MainThreadPaint) {
    779   times_to_fail_reinitialize_ = 0;
    780   times_to_fail_recreate_ = 0;
    781   times_to_lose_on_recreate_ = 100;
    782   RunTest(true, false, false);
    783 }
    784 
    785 TEST_F(LayerTreeHostContextTestLostContextFails,
    786        LoseOnRecreate100_MultiThread_DirectRenderer_ImplSidePaint) {
    787   times_to_fail_reinitialize_ = 0;
    788   times_to_fail_recreate_ = 0;
    789   times_to_lose_on_recreate_ = 100;
    790   RunTest(true, false, true);
    791 }
    792 
    793 TEST_F(LayerTreeHostContextTestLostContextFails,
    794        LoseOnRecreate100_MultiThread_DelegatingRenderer_MainThreadPaint) {
    795   times_to_fail_reinitialize_ = 0;
    796   times_to_fail_recreate_ = 0;
    797   times_to_lose_on_recreate_ = 100;
    798   RunTest(true, true, false);
    799 }
    800 
    801 TEST_F(LayerTreeHostContextTestLostContextFails,
    802        LoseOnRecreate100_MultiThread_DelegatingRenderer_ImplSidePaint) {
    803   times_to_fail_reinitialize_ = 0;
    804   times_to_fail_recreate_ = 0;
    805   times_to_lose_on_recreate_ = 100;
    806   RunTest(true, true, true);
    807 }
    808 
    809 class LayerTreeHostContextTestFinishAllRenderingAfterLoss
    810     : public LayerTreeHostContextTest {
    811  public:
    812   virtual void BeginTest() OVERRIDE {
    813     // Lose the context until the compositor gives up on it.
    814     first_initialized_ = false;
    815     times_to_lose_during_commit_ = 1;
    816     times_to_fail_reinitialize_ = 10;
    817     PostSetNeedsCommitToMainThread();
    818   }
    819 
    820   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
    821     if (first_initialized_) {
    822       EXPECT_FALSE(succeeded);
    823       layer_tree_host()->FinishAllRendering();
    824       EndTest();
    825     } else {
    826       first_initialized_ = true;
    827     }
    828   }
    829 
    830   virtual void AfterTest() OVERRIDE {}
    831 
    832  private:
    833   bool first_initialized_;
    834 };
    835 
    836 SINGLE_AND_MULTI_THREAD_TEST_F(
    837     LayerTreeHostContextTestFinishAllRenderingAfterLoss);
    838 
    839 class LayerTreeHostContextTestLostContextAndEvictTextures
    840     : public LayerTreeHostContextTest {
    841  public:
    842   LayerTreeHostContextTestLostContextAndEvictTextures()
    843       : LayerTreeHostContextTest(),
    844         layer_(FakeContentLayer::Create(&client_)),
    845         impl_host_(0),
    846         num_commits_(0) {}
    847 
    848   virtual void SetupTree() OVERRIDE {
    849     layer_->SetBounds(gfx::Size(10, 20));
    850     layer_tree_host()->SetRootLayer(layer_);
    851     LayerTreeHostContextTest::SetupTree();
    852   }
    853 
    854   virtual void BeginTest() OVERRIDE {
    855     PostSetNeedsCommitToMainThread();
    856   }
    857 
    858   void PostEvictTextures() {
    859     if (HasImplThread()) {
    860       ImplThreadTaskRunner()->PostTask(
    861           FROM_HERE,
    862           base::Bind(
    863               &LayerTreeHostContextTestLostContextAndEvictTextures::
    864               EvictTexturesOnImplThread,
    865               base::Unretained(this)));
    866     } else {
    867       DebugScopedSetImplThread impl(proxy());
    868       EvictTexturesOnImplThread();
    869     }
    870   }
    871 
    872   void EvictTexturesOnImplThread() {
    873     impl_host_->EvictTexturesForTesting();
    874     if (lose_after_evict_)
    875       LoseContext();
    876   }
    877 
    878   virtual void DidCommitAndDrawFrame() OVERRIDE {
    879     if (num_commits_ > 1)
    880       return;
    881     EXPECT_TRUE(layer_->HaveBackingAt(0, 0));
    882     PostEvictTextures();
    883   }
    884 
    885   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
    886     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
    887     if (num_commits_ > 1)
    888       return;
    889     ++num_commits_;
    890     if (!lose_after_evict_)
    891       LoseContext();
    892     impl_host_ = impl;
    893   }
    894 
    895   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
    896     EXPECT_TRUE(succeeded);
    897     EndTest();
    898   }
    899 
    900   virtual void AfterTest() OVERRIDE {}
    901 
    902  protected:
    903   bool lose_after_evict_;
    904   FakeContentLayerClient client_;
    905   scoped_refptr<FakeContentLayer> layer_;
    906   LayerTreeHostImpl* impl_host_;
    907   int num_commits_;
    908 };
    909 
    910 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    911        LoseAfterEvict_SingleThread_DirectRenderer) {
    912   lose_after_evict_ = true;
    913   RunTest(false, false, false);
    914 }
    915 
    916 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    917        LoseAfterEvict_SingleThread_DelegatingRenderer) {
    918   lose_after_evict_ = true;
    919   RunTest(false, true, false);
    920 }
    921 
    922 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    923        LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) {
    924   lose_after_evict_ = true;
    925   RunTest(true, false, false);
    926 }
    927 
    928 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    929        LoseAfterEvict_MultiThread_DirectRenderer_ImplSidePaint) {
    930   lose_after_evict_ = true;
    931   RunTest(true, false, true);
    932 }
    933 
    934 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    935        LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
    936   lose_after_evict_ = true;
    937   RunTest(true, true, false);
    938 }
    939 
    940 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    941        LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
    942   lose_after_evict_ = true;
    943   RunTest(true, true, true);
    944 }
    945 
    946 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    947        LoseBeforeEvict_SingleThread_DirectRenderer) {
    948   lose_after_evict_ = false;
    949   RunTest(false, false, false);
    950 }
    951 
    952 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    953        LoseBeforeEvict_SingleThread_DelegatingRenderer) {
    954   lose_after_evict_ = false;
    955   RunTest(false, true, false);
    956 }
    957 
    958 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    959        LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) {
    960   lose_after_evict_ = false;
    961   RunTest(true, false, false);
    962 }
    963 
    964 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    965        LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) {
    966   lose_after_evict_ = false;
    967   RunTest(true, false, true);
    968 }
    969 
    970 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    971        LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
    972   lose_after_evict_ = false;
    973   RunTest(true, true, false);
    974 }
    975 
    976 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
    977        LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
    978   lose_after_evict_ = false;
    979   RunTest(true, true, true);
    980 }
    981 
    982 class LayerTreeHostContextTestLostContextWhileUpdatingResources
    983     : public LayerTreeHostContextTest {
    984  public:
    985   LayerTreeHostContextTestLostContextWhileUpdatingResources()
    986       : parent_(FakeContentLayer::Create(&client_)),
    987         num_children_(50),
    988         times_to_lose_on_end_query_(3) {}
    989 
    990   virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() OVERRIDE {
    991     scoped_ptr<TestWebGraphicsContext3D> context =
    992         LayerTreeHostContextTest::CreateContext3d();
    993     if (times_to_lose_on_end_query_) {
    994       --times_to_lose_on_end_query_;
    995       context->set_times_end_query_succeeds(5);
    996     }
    997     return context.Pass();
    998   }
    999 
   1000   virtual void SetupTree() OVERRIDE {
   1001     parent_->SetBounds(gfx::Size(num_children_, 1));
   1002 
   1003     for (int i = 0; i < num_children_; i++) {
   1004       scoped_refptr<FakeContentLayer> child =
   1005           FakeContentLayer::Create(&client_);
   1006       child->SetPosition(gfx::PointF(i, 0.f));
   1007       child->SetBounds(gfx::Size(1, 1));
   1008       parent_->AddChild(child);
   1009     }
   1010 
   1011     layer_tree_host()->SetRootLayer(parent_);
   1012     LayerTreeHostContextTest::SetupTree();
   1013   }
   1014 
   1015   virtual void BeginTest() OVERRIDE {
   1016     PostSetNeedsCommitToMainThread();
   1017   }
   1018 
   1019   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1020     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
   1021     EndTest();
   1022   }
   1023 
   1024   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
   1025     EXPECT_TRUE(succeeded);
   1026   }
   1027 
   1028   virtual void AfterTest() OVERRIDE {
   1029     EXPECT_EQ(0, times_to_lose_on_end_query_);
   1030   }
   1031 
   1032  private:
   1033   FakeContentLayerClient client_;
   1034   scoped_refptr<FakeContentLayer> parent_;
   1035   int num_children_;
   1036   int times_to_lose_on_end_query_;
   1037 };
   1038 
   1039 SINGLE_AND_MULTI_THREAD_TEST_F(
   1040     LayerTreeHostContextTestLostContextWhileUpdatingResources);
   1041 
   1042 class LayerTreeHostContextTestLayersNotified
   1043     : public LayerTreeHostContextTest {
   1044  public:
   1045   LayerTreeHostContextTestLayersNotified()
   1046       : LayerTreeHostContextTest(),
   1047         num_commits_(0) {}
   1048 
   1049   virtual void SetupTree() OVERRIDE {
   1050     root_ = FakeContentLayer::Create(&client_);
   1051     child_ = FakeContentLayer::Create(&client_);
   1052     grandchild_ = FakeContentLayer::Create(&client_);
   1053 
   1054     root_->AddChild(child_);
   1055     child_->AddChild(grandchild_);
   1056 
   1057     layer_tree_host()->SetRootLayer(root_);
   1058     LayerTreeHostContextTest::SetupTree();
   1059   }
   1060 
   1061   virtual void BeginTest() OVERRIDE {
   1062     PostSetNeedsCommitToMainThread();
   1063   }
   1064 
   1065   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
   1066     LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
   1067 
   1068     FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>(
   1069         host_impl->active_tree()->root_layer());
   1070     FakeContentLayerImpl* child = static_cast<FakeContentLayerImpl*>(
   1071         root->children()[0]);
   1072     FakeContentLayerImpl* grandchild = static_cast<FakeContentLayerImpl*>(
   1073         child->children()[0]);
   1074 
   1075     ++num_commits_;
   1076     switch (num_commits_) {
   1077       case 1:
   1078         EXPECT_EQ(0u, root->lost_output_surface_count());
   1079         EXPECT_EQ(0u, child->lost_output_surface_count());
   1080         EXPECT_EQ(0u, grandchild->lost_output_surface_count());
   1081         // Lose the context and struggle to recreate it.
   1082         LoseContext();
   1083         times_to_fail_create_ = 1;
   1084         break;
   1085       case 2:
   1086         EXPECT_EQ(1u, root->lost_output_surface_count());
   1087         EXPECT_EQ(1u, child->lost_output_surface_count());
   1088         EXPECT_EQ(1u, grandchild->lost_output_surface_count());
   1089         // Lose the context and again during recreate.
   1090         LoseContext();
   1091         times_to_lose_on_create_ = 1;
   1092         break;
   1093       case 3:
   1094         EXPECT_EQ(3u, root->lost_output_surface_count());
   1095         EXPECT_EQ(3u, child->lost_output_surface_count());
   1096         EXPECT_EQ(3u, grandchild->lost_output_surface_count());
   1097         // Lose the context and again during reinitialization.
   1098         LoseContext();
   1099         times_to_fail_initialize_ = 1;
   1100         break;
   1101       case 4:
   1102         EXPECT_EQ(5u, root->lost_output_surface_count());
   1103         EXPECT_EQ(5u, child->lost_output_surface_count());
   1104         EXPECT_EQ(5u, grandchild->lost_output_surface_count());
   1105         EndTest();
   1106         break;
   1107       default:
   1108         NOTREACHED();
   1109     }
   1110   }
   1111 
   1112   virtual void AfterTest() OVERRIDE {}
   1113 
   1114  private:
   1115   int num_commits_;
   1116 
   1117   FakeContentLayerClient client_;
   1118   scoped_refptr<FakeContentLayer> root_;
   1119   scoped_refptr<FakeContentLayer> child_;
   1120   scoped_refptr<FakeContentLayer> grandchild_;
   1121 };
   1122 
   1123 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
   1124 
   1125 class LayerTreeHostContextTestDontUseLostResources
   1126     : public LayerTreeHostContextTest {
   1127  public:
   1128   virtual void SetupTree() OVERRIDE {
   1129     scoped_refptr<Layer> root_ = Layer::Create();
   1130     root_->SetBounds(gfx::Size(10, 10));
   1131     root_->SetAnchorPoint(gfx::PointF());
   1132     root_->SetIsDrawable(true);
   1133 
   1134     scoped_refptr<FakeDelegatedRendererLayer> delegated_ =
   1135         FakeDelegatedRendererLayer::Create(NULL);
   1136     delegated_->SetBounds(gfx::Size(10, 10));
   1137     delegated_->SetAnchorPoint(gfx::PointF());
   1138     delegated_->SetIsDrawable(true);
   1139     root_->AddChild(delegated_);
   1140 
   1141     scoped_refptr<ContentLayer> content_ = ContentLayer::Create(&client_);
   1142     content_->SetBounds(gfx::Size(10, 10));
   1143     content_->SetAnchorPoint(gfx::PointF());
   1144     content_->SetIsDrawable(true);
   1145     root_->AddChild(content_);
   1146 
   1147     scoped_refptr<TextureLayer> texture_ = TextureLayer::Create(NULL);
   1148     texture_->SetBounds(gfx::Size(10, 10));
   1149     texture_->SetAnchorPoint(gfx::PointF());
   1150     texture_->SetIsDrawable(true);
   1151     root_->AddChild(texture_);
   1152 
   1153     scoped_refptr<ContentLayer> mask_ = ContentLayer::Create(&client_);
   1154     mask_->SetBounds(gfx::Size(10, 10));
   1155     mask_->SetAnchorPoint(gfx::PointF());
   1156 
   1157     scoped_refptr<ContentLayer> content_with_mask_ =
   1158         ContentLayer::Create(&client_);
   1159     content_with_mask_->SetBounds(gfx::Size(10, 10));
   1160     content_with_mask_->SetAnchorPoint(gfx::PointF());
   1161     content_with_mask_->SetIsDrawable(true);
   1162     content_with_mask_->SetMaskLayer(mask_.get());
   1163     root_->AddChild(content_with_mask_);
   1164 
   1165     scoped_refptr<VideoLayer> video_color_ = VideoLayer::Create(
   1166         &color_frame_provider_);
   1167     video_color_->SetBounds(gfx::Size(10, 10));
   1168     video_color_->SetAnchorPoint(gfx::PointF());
   1169     video_color_->SetIsDrawable(true);
   1170     root_->AddChild(video_color_);
   1171 
   1172     scoped_refptr<VideoLayer> video_hw_ = VideoLayer::Create(
   1173         &hw_frame_provider_);
   1174     video_hw_->SetBounds(gfx::Size(10, 10));
   1175     video_hw_->SetAnchorPoint(gfx::PointF());
   1176     video_hw_->SetIsDrawable(true);
   1177     root_->AddChild(video_hw_);
   1178 
   1179     scoped_refptr<VideoLayer> video_scaled_hw_ = VideoLayer::Create(
   1180         &scaled_hw_frame_provider_);
   1181     video_scaled_hw_->SetBounds(gfx::Size(10, 10));
   1182     video_scaled_hw_->SetAnchorPoint(gfx::PointF());
   1183     video_scaled_hw_->SetIsDrawable(true);
   1184     root_->AddChild(video_scaled_hw_);
   1185 
   1186     if (!delegating_renderer()) {
   1187       // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
   1188       scoped_refptr<IOSurfaceLayer> io_surface_ = IOSurfaceLayer::Create();
   1189       io_surface_->SetBounds(gfx::Size(10, 10));
   1190       io_surface_->SetAnchorPoint(gfx::PointF());
   1191       io_surface_->SetIsDrawable(true);
   1192       io_surface_->SetIOSurfaceProperties(1, gfx::Size(10, 10));
   1193       root_->AddChild(io_surface_);
   1194     }
   1195 
   1196     // Enable the hud.
   1197     LayerTreeDebugState debug_state;
   1198     debug_state.show_property_changed_rects = true;
   1199     layer_tree_host()->SetDebugState(debug_state);
   1200 
   1201     scoped_refptr<ScrollbarLayer> scrollbar_ = ScrollbarLayer::Create(
   1202         scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(),
   1203         content_->id());
   1204     scrollbar_->SetBounds(gfx::Size(10, 10));
   1205     scrollbar_->SetAnchorPoint(gfx::PointF());
   1206     scrollbar_->SetIsDrawable(true);
   1207     root_->AddChild(scrollbar_);
   1208 
   1209     layer_tree_host()->SetRootLayer(root_);
   1210     LayerTreeHostContextTest::SetupTree();
   1211   }
   1212 
   1213   virtual void BeginTest() OVERRIDE {
   1214     context_should_support_io_surface_ = true;
   1215     PostSetNeedsCommitToMainThread();
   1216   }
   1217 
   1218   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
   1219     LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
   1220 
   1221     ResourceProvider* resource_provider = host_impl->resource_provider();
   1222 
   1223     if (host_impl->active_tree()->source_frame_number() == 0) {
   1224       // Set up impl resources on the first commit.
   1225 
   1226       scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
   1227       pass_for_quad->SetNew(
   1228           // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
   1229           RenderPass::Id(1, 1),
   1230           gfx::Rect(0, 0, 10, 10),
   1231           gfx::Rect(0, 0, 10, 10),
   1232           gfx::Transform());
   1233 
   1234       scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
   1235       pass->SetNew(
   1236           RenderPass::Id(2, 1),
   1237           gfx::Rect(0, 0, 10, 10),
   1238           gfx::Rect(0, 0, 10, 10),
   1239           gfx::Transform());
   1240       pass->AppendOneOfEveryQuadType(resource_provider, RenderPass::Id(2, 1));
   1241 
   1242       ScopedPtrVector<RenderPass> pass_list;
   1243       pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
   1244       pass_list.push_back(pass.PassAs<RenderPass>());
   1245 
   1246       // First child is the delegated layer.
   1247       FakeDelegatedRendererLayerImpl* delegated_impl =
   1248           static_cast<FakeDelegatedRendererLayerImpl*>(
   1249               host_impl->active_tree()->root_layer()->children()[0]);
   1250       delegated_impl->SetFrameDataForRenderPasses(&pass_list);
   1251       EXPECT_TRUE(pass_list.empty());
   1252 
   1253       // Third child is the texture layer.
   1254       TextureLayerImpl* texture_impl =
   1255           static_cast<TextureLayerImpl*>(
   1256               host_impl->active_tree()->root_layer()->children()[2]);
   1257       texture_impl->set_texture_id(
   1258           resource_provider->GraphicsContext3D()->createTexture());
   1259 
   1260       DCHECK(resource_provider->GraphicsContext3D());
   1261       ResourceProvider::ResourceId texture = resource_provider->CreateResource(
   1262           gfx::Size(4, 4),
   1263           resource_provider->default_resource_type(),
   1264           ResourceProvider::TextureUsageAny);
   1265       ResourceProvider::ScopedWriteLockGL lock(resource_provider, texture);
   1266 
   1267       gpu::Mailbox mailbox;
   1268       resource_provider->GraphicsContext3D()->genMailboxCHROMIUM(mailbox.name);
   1269       unsigned sync_point =
   1270           resource_provider->GraphicsContext3D()->insertSyncPoint();
   1271 
   1272       color_video_frame_ = VideoFrame::CreateColorFrame(
   1273           gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
   1274       hw_video_frame_ = VideoFrame::WrapNativeTexture(
   1275           new VideoFrame::MailboxHolder(
   1276               mailbox,
   1277               sync_point,
   1278               VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()),
   1279           GL_TEXTURE_2D,
   1280           gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4),
   1281           base::TimeDelta(),
   1282           VideoFrame::ReadPixelsCB(),
   1283           base::Closure());
   1284       scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
   1285           new VideoFrame::MailboxHolder(
   1286               mailbox,
   1287               sync_point,
   1288               VideoFrame::MailboxHolder::TextureNoLongerNeededCallback()),
   1289           GL_TEXTURE_2D,
   1290           gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4),
   1291           base::TimeDelta(),
   1292           VideoFrame::ReadPixelsCB(),
   1293           base::Closure());
   1294 
   1295       color_frame_provider_.set_frame(color_video_frame_);
   1296       hw_frame_provider_.set_frame(hw_video_frame_);
   1297       scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
   1298       return;
   1299     }
   1300 
   1301     if (host_impl->active_tree()->source_frame_number() == 3) {
   1302       // On the third commit we're recovering from context loss. Hardware
   1303       // video frames should not be reused by the VideoFrameProvider, but
   1304       // software frames can be.
   1305       hw_frame_provider_.set_frame(NULL);
   1306       scaled_hw_frame_provider_.set_frame(NULL);
   1307     }
   1308   }
   1309 
   1310   virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
   1311                                      LayerTreeHostImpl::FrameData* frame,
   1312                                      bool result) OVERRIDE {
   1313     if (host_impl->active_tree()->source_frame_number() == 2) {
   1314       // Lose the context during draw on the second commit. This will cause
   1315       // a third commit to recover.
   1316       if (context3d_)
   1317         context3d_->set_times_bind_texture_succeeds(4);
   1318     }
   1319     return true;
   1320   }
   1321 
   1322   virtual void DidCommitAndDrawFrame() OVERRIDE {
   1323     ASSERT_TRUE(layer_tree_host()->hud_layer());
   1324     // End the test once we know the 3nd frame drew.
   1325     if (layer_tree_host()->source_frame_number() == 4)
   1326       EndTest();
   1327     else
   1328       layer_tree_host()->SetNeedsCommit();
   1329   }
   1330 
   1331   virtual void AfterTest() OVERRIDE {}
   1332 
   1333  private:
   1334   FakeContentLayerClient client_;
   1335 
   1336   scoped_refptr<Layer> root_;
   1337   scoped_refptr<DelegatedRendererLayer> delegated_;
   1338   scoped_refptr<ContentLayer> content_;
   1339   scoped_refptr<TextureLayer> texture_;
   1340   scoped_refptr<ContentLayer> mask_;
   1341   scoped_refptr<ContentLayer> content_with_mask_;
   1342   scoped_refptr<VideoLayer> video_color_;
   1343   scoped_refptr<VideoLayer> video_hw_;
   1344   scoped_refptr<VideoLayer> video_scaled_hw_;
   1345   scoped_refptr<IOSurfaceLayer> io_surface_;
   1346   scoped_refptr<ScrollbarLayer> scrollbar_;
   1347 
   1348   scoped_refptr<VideoFrame> color_video_frame_;
   1349   scoped_refptr<VideoFrame> hw_video_frame_;
   1350   scoped_refptr<VideoFrame> scaled_hw_video_frame_;
   1351 
   1352   FakeVideoFrameProvider color_frame_provider_;
   1353   FakeVideoFrameProvider hw_frame_provider_;
   1354   FakeVideoFrameProvider scaled_hw_frame_provider_;
   1355 };
   1356 
   1357 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
   1358 
   1359 class LayerTreeHostContextTestLosesFirstOutputSurface
   1360     : public LayerTreeHostContextTest {
   1361  public:
   1362   LayerTreeHostContextTestLosesFirstOutputSurface() {
   1363     // Always fail. This needs to be set before LayerTreeHost is created.
   1364     times_to_lose_on_create_ = 1000;
   1365   }
   1366 
   1367   virtual void BeginTest() OVERRIDE {
   1368     PostSetNeedsCommitToMainThread();
   1369   }
   1370 
   1371   virtual void AfterTest() OVERRIDE {}
   1372 
   1373   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
   1374     EXPECT_FALSE(succeeded);
   1375 
   1376     // If we make it this far without crashing, we pass!
   1377     EndTest();
   1378   }
   1379 
   1380   virtual void DidCommitAndDrawFrame() OVERRIDE {
   1381     EXPECT_TRUE(false);
   1382   }
   1383 };
   1384 
   1385 SINGLE_AND_MULTI_THREAD_TEST_F(
   1386     LayerTreeHostContextTestLosesFirstOutputSurface);
   1387 
   1388 class LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds
   1389     : public LayerTreeHostContextTest {
   1390  public:
   1391   virtual void AfterTest() OVERRIDE {}
   1392 
   1393   virtual void BeginTest() OVERRIDE {
   1394     times_to_fail_initialize_ = 2;
   1395     PostSetNeedsCommitToMainThread();
   1396   }
   1397 
   1398   virtual void DidCommitAndDrawFrame() OVERRIDE {
   1399     EndTest();
   1400   }
   1401 };
   1402 
   1403 SINGLE_AND_MULTI_THREAD_TEST_F(
   1404     LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds);
   1405 
   1406 class LayerTreeHostContextTestRetryWorksWithForcedInit
   1407     : public LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds {
   1408  public:
   1409   virtual void DidFailToInitializeOutputSurface() OVERRIDE {
   1410     LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds
   1411         ::DidFailToInitializeOutputSurface();
   1412 
   1413     if (times_create_failed_ == 1) {
   1414       // CompositeAndReadback force recreates the output surface, which should
   1415       // fail.
   1416       char pixels[4];
   1417       EXPECT_FALSE(layer_tree_host()->CompositeAndReadback(
   1418             &pixels, gfx::Rect(1, 1)));
   1419     }
   1420   }
   1421 };
   1422 
   1423 SINGLE_AND_MULTI_THREAD_TEST_F(
   1424     LayerTreeHostContextTestRetryWorksWithForcedInit);
   1425 
   1426 class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
   1427     : public LayerTreeHostContextTest {
   1428  public:
   1429   virtual void BeginTest() OVERRIDE {
   1430     // This must be called immediately after creating LTH, before the first
   1431     // OutputSurface is initialized.
   1432     ASSERT_TRUE(layer_tree_host()->output_surface_lost());
   1433 
   1434     times_output_surface_created_ = 0;
   1435 
   1436     char pixels[4];
   1437     bool result = layer_tree_host()->CompositeAndReadback(
   1438         &pixels, gfx::Rect(1, 1));
   1439     EXPECT_EQ(!delegating_renderer(), result);
   1440     EXPECT_EQ(1, times_output_surface_created_);
   1441 
   1442     PostSetNeedsCommitToMainThread();
   1443   }
   1444 
   1445   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
   1446     EXPECT_TRUE(succeeded);
   1447     ++times_output_surface_created_;
   1448   }
   1449 
   1450   virtual void DidCommitAndDrawFrame() OVERRIDE {
   1451     EndTest();
   1452   }
   1453 
   1454   virtual void AfterTest() OVERRIDE {
   1455     // Should not try to create output surface again after successfully
   1456     // created by CompositeAndReadback.
   1457     EXPECT_EQ(1, times_output_surface_created_);
   1458   }
   1459 
   1460  private:
   1461   int times_output_surface_created_;
   1462 };
   1463 
   1464 SINGLE_AND_MULTI_THREAD_TEST_F(
   1465     LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit);
   1466 
   1467 class ImplSidePaintingLayerTreeHostContextTest
   1468     : public LayerTreeHostContextTest {
   1469  public:
   1470   virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
   1471     settings->impl_side_painting = true;
   1472   }
   1473 };
   1474 
   1475 class LayerTreeHostContextTestImplSidePainting
   1476     : public ImplSidePaintingLayerTreeHostContextTest {
   1477  public:
   1478   virtual void SetupTree() OVERRIDE {
   1479     scoped_refptr<Layer> root = Layer::Create();
   1480     root->SetBounds(gfx::Size(10, 10));
   1481     root->SetAnchorPoint(gfx::PointF());
   1482     root->SetIsDrawable(true);
   1483 
   1484     scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
   1485     picture->SetBounds(gfx::Size(10, 10));
   1486     picture->SetAnchorPoint(gfx::PointF());
   1487     picture->SetIsDrawable(true);
   1488     root->AddChild(picture);
   1489 
   1490     layer_tree_host()->SetRootLayer(root);
   1491     LayerTreeHostContextTest::SetupTree();
   1492   }
   1493 
   1494   virtual void BeginTest() OVERRIDE {
   1495     times_to_lose_during_commit_ = 1;
   1496     PostSetNeedsCommitToMainThread();
   1497   }
   1498 
   1499   virtual void AfterTest() OVERRIDE {}
   1500 
   1501   virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
   1502     EXPECT_TRUE(succeeded);
   1503     EndTest();
   1504   }
   1505 
   1506  private:
   1507   FakeContentLayerClient client_;
   1508 };
   1509 
   1510 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
   1511 
   1512 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
   1513  public:
   1514   ScrollbarLayerLostContext() : commits_(0) {}
   1515 
   1516   virtual void BeginTest() OVERRIDE {
   1517     scoped_refptr<Layer> scroll_layer = Layer::Create();
   1518     scrollbar_layer_ = FakeScrollbarLayer::Create(
   1519         false, true, scroll_layer->id());
   1520     scrollbar_layer_->SetBounds(gfx::Size(10, 100));
   1521     layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
   1522     layer_tree_host()->root_layer()->AddChild(scroll_layer);
   1523     PostSetNeedsCommitToMainThread();
   1524   }
   1525 
   1526   virtual void AfterTest() OVERRIDE {}
   1527 
   1528   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1529     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
   1530 
   1531     ++commits_;
   1532     switch (commits_) {
   1533       case 1:
   1534         // First (regular) update, we should upload 2 resources (thumb, and
   1535         // backtrack).
   1536         EXPECT_EQ(1, scrollbar_layer_->update_count());
   1537         LoseContext();
   1538         break;
   1539       case 2:
   1540         // Second update, after the lost context, we should still upload 2
   1541         // resources even if the contents haven't changed.
   1542         EXPECT_EQ(2, scrollbar_layer_->update_count());
   1543         EndTest();
   1544         break;
   1545       default:
   1546         NOTREACHED();
   1547     }
   1548   }
   1549 
   1550  private:
   1551   int commits_;
   1552   scoped_refptr<FakeScrollbarLayer> scrollbar_layer_;
   1553 };
   1554 
   1555 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
   1556 
   1557 class LayerTreeHostContextTestFailsToCreateSurface
   1558     : public LayerTreeHostContextTest {
   1559  public:
   1560   LayerTreeHostContextTestFailsToCreateSurface()
   1561       : LayerTreeHostContextTest(),
   1562         failure_count_(0) {
   1563     times_to_lose_on_create_ = 10;
   1564   }
   1565 
   1566   virtual void BeginTest() OVERRIDE {
   1567     PostSetNeedsCommitToMainThread();
   1568   }
   1569 
   1570   virtual void AfterTest() OVERRIDE {}
   1571 
   1572   virtual void DidInitializeOutputSurface(bool success) OVERRIDE {
   1573     EXPECT_FALSE(success);
   1574     EXPECT_EQ(0, failure_count_);
   1575     times_to_lose_on_create_ = 0;
   1576     failure_count_++;
   1577     // Normally, the embedder should stop trying to use the compositor at
   1578     // this point, but let's force it back into action when we shouldn't.
   1579     char pixels[4];
   1580     EXPECT_FALSE(
   1581         layer_tree_host()->CompositeAndReadback(pixels, gfx::Rect(1, 1)));
   1582     // If we've made it this far without crashing, we've succeeded.
   1583     EndTest();
   1584   }
   1585 
   1586  private:
   1587   int failure_count_;
   1588 };
   1589 
   1590 SINGLE_AND_MULTI_THREAD_TEST_F(
   1591     LayerTreeHostContextTestFailsToCreateSurface);
   1592 
   1593 // Not reusing LayerTreeTest because it expects creating LTH to always succeed.
   1594 class LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface
   1595     : public testing::Test,
   1596       public FakeLayerTreeHostClient {
   1597  public:
   1598   LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface()
   1599       : FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D) {}
   1600 
   1601   // FakeLayerTreeHostClient implementation.
   1602   virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
   1603       OVERRIDE {
   1604     return scoped_ptr<OutputSurface>();
   1605   }
   1606 
   1607   void RunTest(bool threaded,
   1608                bool delegating_renderer,
   1609                bool impl_side_painting) {
   1610     scoped_ptr<base::Thread> impl_thread;
   1611     if (threaded) {
   1612       impl_thread.reset(new base::Thread("LayerTreeTest"));
   1613       ASSERT_TRUE(impl_thread->Start());
   1614       ASSERT_TRUE(impl_thread->message_loop_proxy().get());
   1615     }
   1616 
   1617     LayerTreeSettings settings;
   1618     settings.impl_side_painting = impl_side_painting;
   1619     scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create(
   1620         this,
   1621         settings,
   1622         impl_thread ? impl_thread->message_loop_proxy() : NULL);
   1623     EXPECT_FALSE(layer_tree_host);
   1624   }
   1625 };
   1626 
   1627 SINGLE_AND_MULTI_THREAD_TEST_F(
   1628     LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface);
   1629 
   1630 class UIResourceLostTest : public LayerTreeHostContextTest {
   1631  public:
   1632   UIResourceLostTest() : time_step_(0) {}
   1633   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
   1634   virtual void AfterTest() OVERRIDE {}
   1635 
   1636  protected:
   1637   int time_step_;
   1638   scoped_ptr<FakeScopedUIResource> ui_resource_;
   1639 };
   1640 
   1641 // Losing context after an UI resource has been created.
   1642 class UIResourceLostAfterCommit : public UIResourceLostTest {
   1643  public:
   1644   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1645     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
   1646     switch (time_step_) {
   1647       case 0:
   1648         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
   1649         // Expects a valid UIResourceId.
   1650         EXPECT_NE(0, ui_resource_->id());
   1651         PostSetNeedsCommitToMainThread();
   1652         break;
   1653       case 1:
   1654         // The resource should have been created on LTHI after the commit.
   1655         if (!layer_tree_host()->settings().impl_side_painting)
   1656           EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1657         PostSetNeedsCommitToMainThread();
   1658         break;
   1659       case 2:
   1660         LoseContext();
   1661         break;
   1662       case 3:
   1663         // The resources should have been recreated. The bitmap callback should
   1664         // have been called once with the resource_lost flag set to true.
   1665         EXPECT_EQ(1, ui_resource_->lost_resource_count);
   1666         // Resource Id on the impl-side have been recreated as well. Note
   1667         // that the same UIResourceId persists after the context lost.
   1668         if (!layer_tree_host()->settings().impl_side_painting)
   1669           EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1670         PostSetNeedsCommitToMainThread();
   1671         break;
   1672       case 4:
   1673         // Release resource before ending test.
   1674         ui_resource_.reset();
   1675         EndTest();
   1676         break;
   1677     }
   1678   }
   1679 
   1680   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1681     LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
   1682     switch (time_step_) {
   1683       case 1:
   1684         if (layer_tree_host()->settings().impl_side_painting)
   1685           EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1686         break;
   1687       case 3:
   1688         if (layer_tree_host()->settings().impl_side_painting)
   1689           EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1690         break;
   1691     }
   1692     ++time_step_;
   1693   }
   1694 };
   1695 
   1696 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
   1697 
   1698 // Losing context before UI resource requests can be commited.  Three sequences
   1699 // of creation/deletion are considered:
   1700 // 1. Create one resource -> Context Lost => Expect the resource to have been
   1701 // created.
   1702 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
   1703 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
   1704 // test_id1_ to have been created.
   1705 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
   1706 // the resource to not exist in the manager.
   1707 class UIResourceLostBeforeCommit : public UIResourceLostTest {
   1708  public:
   1709   UIResourceLostBeforeCommit()
   1710       : test_id0_(0),
   1711         test_id1_(0) {}
   1712 
   1713   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1714     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
   1715     switch (time_step_) {
   1716       case 0:
   1717         // Sequence 1:
   1718         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
   1719         LoseContext();
   1720         // Resource Id on the impl-side should no longer be valid after
   1721         // context is lost.
   1722         EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1723         break;
   1724       case 1:
   1725         // The resources should have been recreated.
   1726         EXPECT_EQ(2, ui_resource_->resource_create_count);
   1727         // "resource lost" callback was called once for the resource in the
   1728         // resource map.
   1729         EXPECT_EQ(1, ui_resource_->lost_resource_count);
   1730         // Resource Id on the impl-side have been recreated as well. Note
   1731         // that the same UIResourceId persists after the context lost.
   1732         if (!layer_tree_host()->settings().impl_side_painting)
   1733           EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1734         PostSetNeedsCommitToMainThread();
   1735         break;
   1736       case 2:
   1737         // Sequence 2:
   1738         // Currently one resource has been created.
   1739         test_id0_ = ui_resource_->id();
   1740         // Delete this resource.
   1741         ui_resource_.reset();
   1742         // Create another resource.
   1743         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
   1744         test_id1_ = ui_resource_->id();
   1745         // Sanity check that two resource creations return different ids.
   1746         EXPECT_NE(test_id0_, test_id1_);
   1747         // Lose the context before commit.
   1748         LoseContext();
   1749         break;
   1750       case 3:
   1751         if (!layer_tree_host()->settings().impl_side_painting) {
   1752           // The previous resource should have been deleted.
   1753           EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
   1754           // The second resource should have been created.
   1755           EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
   1756         }
   1757 
   1758         // The second resource called the resource callback once and since the
   1759         // context is lost, a "resource lost" callback was also issued.
   1760         EXPECT_EQ(2, ui_resource_->resource_create_count);
   1761         EXPECT_EQ(1, ui_resource_->lost_resource_count);
   1762         // Clear the manager of resources.
   1763         ui_resource_.reset();
   1764         PostSetNeedsCommitToMainThread();
   1765         break;
   1766       case 4:
   1767         // Sequence 3:
   1768         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
   1769         test_id0_ = ui_resource_->id();
   1770         // Sanity check the UIResourceId should not be 0.
   1771         EXPECT_NE(0, test_id0_);
   1772         // Usually ScopedUIResource are deleted from the manager in their
   1773         // destructor (so usually ui_resource_.reset()).  But here we need
   1774         // ui_resource_ for the next step, so call DeleteUIResource directly.
   1775         layer_tree_host()->DeleteUIResource(test_id0_);
   1776         LoseContext();
   1777         break;
   1778       case 5:
   1779         // Expect the resource callback to have been called once.
   1780         EXPECT_EQ(1, ui_resource_->resource_create_count);
   1781         // No "resource lost" callbacks.
   1782         EXPECT_EQ(0, ui_resource_->lost_resource_count);
   1783         if (!layer_tree_host()->settings().impl_side_painting) {
   1784           // The UI resource id should not be valid
   1785           EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
   1786         }
   1787         PostSetNeedsCommitToMainThread();
   1788         break;
   1789       case 6:
   1790         ui_resource_.reset();
   1791         EndTest();
   1792         break;
   1793     }
   1794   }
   1795 
   1796   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1797     LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
   1798     switch (time_step_) {
   1799       case 1:
   1800         if (layer_tree_host()->settings().impl_side_painting)
   1801           EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1802         break;
   1803       case 3:
   1804         if (layer_tree_host()->settings().impl_side_painting) {
   1805           EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
   1806           EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
   1807         }
   1808         break;
   1809       case 5:
   1810         if (layer_tree_host()->settings().impl_side_painting)
   1811           EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
   1812         break;
   1813     }
   1814     ++time_step_;
   1815   }
   1816 
   1817  private:
   1818   UIResourceId test_id0_;
   1819   UIResourceId test_id1_;
   1820 };
   1821 
   1822 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
   1823 
   1824 // Losing UI resource before the pending trees is activated but after the
   1825 // commit.  Impl-side-painting only.
   1826 class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
   1827   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1828     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
   1829     switch (time_step_) {
   1830       case 0:
   1831         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
   1832         PostSetNeedsCommitToMainThread();
   1833         break;
   1834       case 2:
   1835         PostSetNeedsCommitToMainThread();
   1836         break;
   1837       case 3:
   1838         test_id_ = ui_resource_->id();
   1839         ui_resource_.reset();
   1840         PostSetNeedsCommitToMainThread();
   1841         break;
   1842       case 4:
   1843         PostSetNeedsCommitToMainThread();
   1844         break;
   1845       case 5:
   1846         EndTest();
   1847         break;
   1848     }
   1849   }
   1850 
   1851   virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1852     switch (time_step_) {
   1853       case 0:
   1854         break;
   1855       case 1:
   1856         // The resource creation callback has been called.
   1857         EXPECT_EQ(1, ui_resource_->resource_create_count);
   1858         // The resource is not yet lost (sanity check).
   1859         EXPECT_EQ(0, ui_resource_->lost_resource_count);
   1860         // The resource should not have been created yet on the impl-side.
   1861         EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1862         LoseContext();
   1863         break;
   1864       case 3:
   1865         LoseContext();
   1866         break;
   1867     }
   1868   }
   1869 
   1870   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
   1871     LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
   1872     switch (time_step_) {
   1873       case 1:
   1874         // The pending requests on the impl-side should have been processed.
   1875         EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
   1876         break;
   1877       case 2:
   1878         // The "lost resource" callback should have been called once.
   1879         EXPECT_EQ(1, ui_resource_->lost_resource_count);
   1880         break;
   1881       case 4:
   1882         // The resource is deleted and should not be in the manager.  Use
   1883         // test_id_ since ui_resource_ has been deleted.
   1884         EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
   1885         break;
   1886     }
   1887     ++time_step_;
   1888   }
   1889 
   1890  private:
   1891   UIResourceId test_id_;
   1892 };
   1893 
   1894 TEST_F(UIResourceLostBeforeActivateTree,
   1895        RunMultiThread_DirectRenderer_ImplSidePaint) {
   1896   RunTest(true, false, true);
   1897 }
   1898 
   1899 TEST_F(UIResourceLostBeforeActivateTree,
   1900        RunMultiThread_DelegatingRenderer_ImplSidePaint) {
   1901   RunTest(true, true, true);
   1902 }
   1903 
   1904 }  // namespace
   1905 }  // namespace cc
   1906