Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / cc / trees / layer_tree_host_unittest_context.cc
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cc/trees/layer_tree_host.h"
6
7 #include "base/basictypes.h"
8 #include "cc/layers/content_layer.h"
9 #include "cc/layers/delegated_frame_provider.h"
10 #include "cc/layers/delegated_frame_resource_collection.h"
11 #include "cc/layers/heads_up_display_layer.h"
12 #include "cc/layers/io_surface_layer.h"
13 #include "cc/layers/layer_impl.h"
14 #include "cc/layers/painted_scrollbar_layer.h"
15 #include "cc/layers/picture_layer.h"
16 #include "cc/layers/texture_layer.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/layers/video_layer.h"
19 #include "cc/layers/video_layer_impl.h"
20 #include "cc/output/filter_operations.h"
21 #include "cc/test/fake_content_layer.h"
22 #include "cc/test/fake_content_layer_client.h"
23 #include "cc/test/fake_content_layer_impl.h"
24 #include "cc/test/fake_delegated_renderer_layer.h"
25 #include "cc/test/fake_delegated_renderer_layer_impl.h"
26 #include "cc/test/fake_layer_tree_host_client.h"
27 #include "cc/test/fake_output_surface.h"
28 #include "cc/test/fake_output_surface_client.h"
29 #include "cc/test/fake_painted_scrollbar_layer.h"
30 #include "cc/test/fake_scoped_ui_resource.h"
31 #include "cc/test/fake_scrollbar.h"
32 #include "cc/test/fake_video_frame_provider.h"
33 #include "cc/test/layer_tree_test.h"
34 #include "cc/test/render_pass_test_common.h"
35 #include "cc/test/test_context_provider.h"
36 #include "cc/test/test_shared_bitmap_manager.h"
37 #include "cc/test/test_web_graphics_context_3d.h"
38 #include "cc/trees/layer_tree_host_impl.h"
39 #include "cc/trees/layer_tree_impl.h"
40 #include "cc/trees/single_thread_proxy.h"
41 #include "gpu/GLES2/gl2extchromium.h"
42 #include "media/base/media.h"
43
44 using media::VideoFrame;
45
46 namespace cc {
47 namespace {
48
49 // These tests deal with losing the 3d graphics context.
50 class LayerTreeHostContextTest : public LayerTreeTest {
51  public:
52   LayerTreeHostContextTest()
53       : LayerTreeTest(),
54         context3d_(NULL),
55         times_to_fail_create_(0),
56         times_to_lose_during_commit_(0),
57         times_to_lose_during_draw_(0),
58         times_to_fail_recreate_(0),
59         times_to_expect_create_failed_(0),
60         times_create_failed_(0),
61         committed_at_least_once_(false),
62         context_should_support_io_surface_(false),
63         fallback_context_works_(false) {
64     media::InitializeMediaLibraryForTesting();
65   }
66
67   void LoseContext() {
68     context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
69                                     GL_INNOCENT_CONTEXT_RESET_ARB);
70     context3d_ = NULL;
71   }
72
73   virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
74     return TestWebGraphicsContext3D::Create();
75   }
76
77   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
78       OVERRIDE {
79     if (times_to_fail_create_) {
80       --times_to_fail_create_;
81       ExpectCreateToFail();
82       return scoped_ptr<FakeOutputSurface>();
83     }
84
85     scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
86     context3d_ = context3d.get();
87
88     if (context_should_support_io_surface_) {
89       context3d_->set_have_extension_io_surface(true);
90       context3d_->set_have_extension_egl_image(true);
91     }
92
93     if (delegating_renderer())
94       return FakeOutputSurface::CreateDelegating3d(context3d.Pass());
95     else
96       return FakeOutputSurface::Create3d(context3d.Pass());
97   }
98
99   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
100       LayerTreeHostImpl* host_impl,
101       LayerTreeHostImpl::FrameData* frame,
102       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
103     EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
104     if (!times_to_lose_during_draw_)
105       return draw_result;
106
107     --times_to_lose_during_draw_;
108     LoseContext();
109
110     times_to_fail_create_ = times_to_fail_recreate_;
111     times_to_fail_recreate_ = 0;
112
113     return draw_result;
114   }
115
116   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
117     committed_at_least_once_ = true;
118
119     if (!times_to_lose_during_commit_)
120       return;
121     --times_to_lose_during_commit_;
122     LoseContext();
123
124     times_to_fail_create_ = times_to_fail_recreate_;
125     times_to_fail_recreate_ = 0;
126   }
127
128   virtual void DidFailToInitializeOutputSurface() OVERRIDE {
129     ++times_create_failed_;
130   }
131
132   virtual void TearDown() OVERRIDE {
133     LayerTreeTest::TearDown();
134     EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
135   }
136
137   void ExpectCreateToFail() { ++times_to_expect_create_failed_; }
138
139  protected:
140   TestWebGraphicsContext3D* context3d_;
141   int times_to_fail_create_;
142   int times_to_lose_during_commit_;
143   int times_to_lose_during_draw_;
144   int times_to_fail_recreate_;
145   int times_to_expect_create_failed_;
146   int times_create_failed_;
147   bool committed_at_least_once_;
148   bool context_should_support_io_surface_;
149   bool fallback_context_works_;
150 };
151
152 class LayerTreeHostContextTestLostContextSucceeds
153     : public LayerTreeHostContextTest {
154  public:
155   LayerTreeHostContextTestLostContextSucceeds()
156       : LayerTreeHostContextTest(),
157         test_case_(0),
158         num_losses_(0),
159         num_losses_last_test_case_(-1),
160         recovered_context_(true),
161         first_initialized_(false) {}
162
163   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
164
165   virtual void DidInitializeOutputSurface() OVERRIDE {
166     if (first_initialized_)
167       ++num_losses_;
168     else
169       first_initialized_ = true;
170
171     recovered_context_ = true;
172   }
173
174   virtual void AfterTest() OVERRIDE { EXPECT_EQ(7u, test_case_); }
175
176   virtual void DidCommitAndDrawFrame() OVERRIDE {
177     // If the last frame had a context loss, then we'll commit again to
178     // recover.
179     if (!recovered_context_)
180       return;
181     if (times_to_lose_during_commit_)
182       return;
183     if (times_to_lose_during_draw_)
184       return;
185
186     recovered_context_ = false;
187     if (NextTestCase())
188       InvalidateAndSetNeedsCommit();
189     else
190       EndTest();
191   }
192
193   virtual void InvalidateAndSetNeedsCommit() {
194     // Cause damage so we try to draw.
195     layer_tree_host()->root_layer()->SetNeedsDisplay();
196     layer_tree_host()->SetNeedsCommit();
197   }
198
199   bool NextTestCase() {
200     static const TestCase kTests[] = {
201         // Losing the context and failing to recreate it (or losing it again
202         // immediately) a small number of times should succeed.
203         {1,      // times_to_lose_during_commit
204          0,      // times_to_lose_during_draw
205          0,      // times_to_fail_recreate
206          false,  // fallback_context_works
207         },
208         {0,      // times_to_lose_during_commit
209          1,      // times_to_lose_during_draw
210          0,      // times_to_fail_recreate
211          false,  // fallback_context_works
212         },
213         {1,      // times_to_lose_during_commit
214          0,      // times_to_lose_during_draw
215          3,      // times_to_fail_recreate
216          false,  // fallback_context_works
217         },
218         {0,      // times_to_lose_during_commit
219          1,      // times_to_lose_during_draw
220          3,      // times_to_fail_recreate
221          false,  // fallback_context_works
222         },
223         // Losing the context and recreating it any number of times should
224         // succeed.
225         {10,     // times_to_lose_during_commit
226          0,      // times_to_lose_during_draw
227          0,      // times_to_fail_recreate
228          false,  // fallback_context_works
229         },
230         {0,      // times_to_lose_during_commit
231          10,     // times_to_lose_during_draw
232          0,      // times_to_fail_recreate
233          false,  // fallback_context_works
234         },
235         // Losing the context, failing to reinitialize it, and making a fallback
236         // context should work.
237         {0,     // times_to_lose_during_commit
238          1,     // times_to_lose_during_draw
239          0,     // times_to_fail_recreate
240          true,  // fallback_context_works
241         }, };
242
243     if (test_case_ >= arraysize(kTests))
244       return false;
245     // Make sure that we lost our context at least once in the last test run so
246     // the test did something.
247     EXPECT_GT(num_losses_, num_losses_last_test_case_);
248     num_losses_last_test_case_ = num_losses_;
249
250     times_to_lose_during_commit_ =
251         kTests[test_case_].times_to_lose_during_commit;
252     times_to_lose_during_draw_ = kTests[test_case_].times_to_lose_during_draw;
253     times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
254     fallback_context_works_ = kTests[test_case_].fallback_context_works;
255     ++test_case_;
256     return true;
257   }
258
259   struct TestCase {
260     int times_to_lose_during_commit;
261     int times_to_lose_during_draw;
262     int times_to_fail_recreate;
263     bool fallback_context_works;
264   };
265
266  protected:
267   size_t test_case_;
268   int num_losses_;
269   int num_losses_last_test_case_;
270   bool recovered_context_;
271   bool first_initialized_;
272 };
273
274 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
275
276 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
277     : public LayerTreeHostContextTest {
278  public:
279   LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
280       : LayerTreeHostContextTest() {}
281
282   virtual void WillBeginTest() OVERRIDE {
283     // Override and do not signal SetLayerTreeHostClientReady.
284   }
285
286   virtual void BeginTest() OVERRIDE {
287     PostSetNeedsCommitToMainThread();
288     EndTest();
289   }
290
291   virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
292       OVERRIDE {
293     EXPECT_TRUE(false);
294     return scoped_ptr<OutputSurface>();
295   }
296
297   virtual void DidInitializeOutputSurface() OVERRIDE { EXPECT_TRUE(false); }
298
299   virtual void AfterTest() OVERRIDE {
300   }
301 };
302
303 MULTI_THREAD_TEST_F(LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
304
305 class LayerTreeHostContextTestLostContextSucceedsWithContent
306     : public LayerTreeHostContextTestLostContextSucceeds {
307  public:
308   virtual void SetupTree() OVERRIDE {
309     root_ = Layer::Create();
310     root_->SetBounds(gfx::Size(10, 10));
311     root_->SetAnchorPoint(gfx::PointF());
312     root_->SetIsDrawable(true);
313
314     content_ = FakeContentLayer::Create(&client_);
315     content_->SetBounds(gfx::Size(10, 10));
316     content_->SetAnchorPoint(gfx::PointF());
317     content_->SetIsDrawable(true);
318
319     root_->AddChild(content_);
320
321     layer_tree_host()->SetRootLayer(root_);
322     LayerTreeHostContextTest::SetupTree();
323   }
324
325   virtual void InvalidateAndSetNeedsCommit() OVERRIDE {
326     // Invalidate the render surface so we don't try to use a cached copy of the
327     // surface.  We want to make sure to test the drawing paths for drawing to
328     // a child surface.
329     content_->SetNeedsDisplay();
330     LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
331   }
332
333   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
334     FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>(
335         host_impl->active_tree()->root_layer()->children()[0]);
336     // Even though the context was lost, we should have a resource. The
337     // TestWebGraphicsContext3D ensures that this resource is created with
338     // the active context.
339     EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
340   }
341
342  protected:
343   FakeContentLayerClient client_;
344   scoped_refptr<Layer> root_;
345   scoped_refptr<ContentLayer> content_;
346 };
347
348 // This test uses TiledLayer to check for a working context.
349 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
350     LayerTreeHostContextTestLostContextSucceedsWithContent);
351
352 class LayerTreeHostContextTestCreateOutputSurfaceFails
353     : public LayerTreeHostContextTest {
354  public:
355   // Run a test that initially fails OutputSurface creation |times_to_fail|
356   // times. If |expect_fallback_attempt| is |true|, an attempt to create a
357   // fallback/software OutputSurface is expected to occur.
358   LayerTreeHostContextTestCreateOutputSurfaceFails(int times_to_fail,
359                                                    bool expect_fallback_attempt)
360       : times_to_fail_(times_to_fail),
361         expect_fallback_attempt_(expect_fallback_attempt),
362         did_attempt_fallback_(false),
363         times_initialized_(0) {}
364
365   virtual void BeginTest() OVERRIDE {
366     times_to_fail_create_ = times_to_fail_;
367     PostSetNeedsCommitToMainThread();
368   }
369
370   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
371       OVERRIDE {
372     scoped_ptr<FakeOutputSurface> surface =
373         LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
374
375     if (surface)
376       EXPECT_EQ(times_to_fail_, times_create_failed_);
377
378     did_attempt_fallback_ = fallback;
379     return surface.Pass();
380   }
381
382   virtual void DidInitializeOutputSurface() OVERRIDE { times_initialized_++; }
383
384   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
385     EndTest();
386   }
387
388   virtual void AfterTest() OVERRIDE {
389     EXPECT_EQ(times_to_fail_, times_create_failed_);
390     EXPECT_NE(0, times_initialized_);
391     EXPECT_EQ(expect_fallback_attempt_, did_attempt_fallback_);
392   }
393
394  private:
395   int times_to_fail_;
396   bool expect_fallback_attempt_;
397   bool did_attempt_fallback_;
398   int times_initialized_;
399 };
400
401 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
402     : public LayerTreeHostContextTestCreateOutputSurfaceFails {
403  public:
404   LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
405       : LayerTreeHostContextTestCreateOutputSurfaceFails(1, false) {}
406 };
407
408 SINGLE_AND_MULTI_THREAD_TEST_F(
409     LayerTreeHostContextTestCreateOutputSurfaceFailsOnce);
410
411 // After 4 failures we expect an attempt to create a fallback/software
412 // OutputSurface.
413 class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
414     : public LayerTreeHostContextTestCreateOutputSurfaceFails {
415  public:
416   LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback()
417       : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true) {}
418 };
419
420 SINGLE_AND_MULTI_THREAD_TEST_F(
421     LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback);
422
423 class LayerTreeHostContextTestLostContextAndEvictTextures
424     : public LayerTreeHostContextTest {
425  public:
426   LayerTreeHostContextTestLostContextAndEvictTextures()
427       : LayerTreeHostContextTest(),
428         layer_(FakeContentLayer::Create(&client_)),
429         impl_host_(0),
430         num_commits_(0) {}
431
432   virtual void SetupTree() OVERRIDE {
433     layer_->SetBounds(gfx::Size(10, 20));
434     layer_tree_host()->SetRootLayer(layer_);
435     LayerTreeHostContextTest::SetupTree();
436   }
437
438   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
439
440   void PostEvictTextures() {
441     if (HasImplThread()) {
442       ImplThreadTaskRunner()->PostTask(
443           FROM_HERE,
444           base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
445                           EvictTexturesOnImplThread,
446                      base::Unretained(this)));
447     } else {
448       DebugScopedSetImplThread impl(proxy());
449       EvictTexturesOnImplThread();
450     }
451   }
452
453   void EvictTexturesOnImplThread() {
454     impl_host_->EvictTexturesForTesting();
455     if (lose_after_evict_)
456       LoseContext();
457   }
458
459   virtual void DidCommitAndDrawFrame() OVERRIDE {
460     if (num_commits_ > 1)
461       return;
462     EXPECT_TRUE(layer_->HaveBackingAt(0, 0));
463     PostEvictTextures();
464   }
465
466   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
467     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
468     if (num_commits_ > 1)
469       return;
470     ++num_commits_;
471     if (!lose_after_evict_)
472       LoseContext();
473     impl_host_ = impl;
474   }
475
476   virtual void DidInitializeOutputSurface() OVERRIDE { EndTest(); }
477
478   virtual void AfterTest() OVERRIDE {}
479
480  protected:
481   bool lose_after_evict_;
482   FakeContentLayerClient client_;
483   scoped_refptr<FakeContentLayer> layer_;
484   LayerTreeHostImpl* impl_host_;
485   int num_commits_;
486 };
487
488 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
489        LoseAfterEvict_SingleThread_DirectRenderer) {
490   lose_after_evict_ = true;
491   RunTest(false, false, false);
492 }
493
494 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
495        LoseAfterEvict_SingleThread_DelegatingRenderer) {
496   lose_after_evict_ = true;
497   RunTest(false, true, false);
498 }
499
500 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
501        LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) {
502   lose_after_evict_ = true;
503   RunTest(true, false, false);
504 }
505
506 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
507        LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
508   lose_after_evict_ = true;
509   RunTest(true, true, false);
510 }
511
512 // Flaky on all platforms, http://crbug.com/310979
513 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
514        DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
515   lose_after_evict_ = true;
516   RunTest(true, true, true);
517 }
518
519 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
520        LoseBeforeEvict_SingleThread_DirectRenderer) {
521   lose_after_evict_ = false;
522   RunTest(false, false, false);
523 }
524
525 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
526        LoseBeforeEvict_SingleThread_DelegatingRenderer) {
527   lose_after_evict_ = false;
528   RunTest(false, true, false);
529 }
530
531 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
532        LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) {
533   lose_after_evict_ = false;
534   RunTest(true, false, false);
535 }
536
537 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
538        LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) {
539   lose_after_evict_ = false;
540   RunTest(true, false, true);
541 }
542
543 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
544        LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
545   lose_after_evict_ = false;
546   RunTest(true, true, false);
547 }
548
549 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
550        LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
551   lose_after_evict_ = false;
552   RunTest(true, true, true);
553 }
554
555 class LayerTreeHostContextTestLostContextWhileUpdatingResources
556     : public LayerTreeHostContextTest {
557  public:
558   LayerTreeHostContextTestLostContextWhileUpdatingResources()
559       : parent_(FakeContentLayer::Create(&client_)),
560         num_children_(50),
561         times_to_lose_on_end_query_(3) {}
562
563   virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() OVERRIDE {
564     scoped_ptr<TestWebGraphicsContext3D> context =
565         LayerTreeHostContextTest::CreateContext3d();
566     if (times_to_lose_on_end_query_) {
567       --times_to_lose_on_end_query_;
568       context->set_times_end_query_succeeds(5);
569     }
570     return context.Pass();
571   }
572
573   virtual void SetupTree() OVERRIDE {
574     parent_->SetBounds(gfx::Size(num_children_, 1));
575
576     for (int i = 0; i < num_children_; i++) {
577       scoped_refptr<FakeContentLayer> child =
578           FakeContentLayer::Create(&client_);
579       child->SetPosition(gfx::PointF(i, 0.f));
580       child->SetBounds(gfx::Size(1, 1));
581       parent_->AddChild(child);
582     }
583
584     layer_tree_host()->SetRootLayer(parent_);
585     LayerTreeHostContextTest::SetupTree();
586   }
587
588   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
589
590   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
591     EXPECT_EQ(0, times_to_lose_on_end_query_);
592     EndTest();
593   }
594
595   virtual void AfterTest() OVERRIDE {
596     EXPECT_EQ(0, times_to_lose_on_end_query_);
597   }
598
599  private:
600   FakeContentLayerClient client_;
601   scoped_refptr<FakeContentLayer> parent_;
602   int num_children_;
603   int times_to_lose_on_end_query_;
604 };
605
606 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
607     LayerTreeHostContextTestLostContextWhileUpdatingResources);
608
609 class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest {
610  public:
611   LayerTreeHostContextTestLayersNotified()
612       : LayerTreeHostContextTest(), num_commits_(0) {}
613
614   virtual void SetupTree() OVERRIDE {
615     root_ = FakeContentLayer::Create(&client_);
616     child_ = FakeContentLayer::Create(&client_);
617     grandchild_ = FakeContentLayer::Create(&client_);
618
619     root_->AddChild(child_);
620     child_->AddChild(grandchild_);
621
622     layer_tree_host()->SetRootLayer(root_);
623     LayerTreeHostContextTest::SetupTree();
624   }
625
626   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
627
628   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
629     LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
630
631     FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>(
632         host_impl->active_tree()->root_layer());
633     FakeContentLayerImpl* child =
634         static_cast<FakeContentLayerImpl*>(root->children()[0]);
635     FakeContentLayerImpl* grandchild =
636         static_cast<FakeContentLayerImpl*>(child->children()[0]);
637
638     ++num_commits_;
639     switch (num_commits_) {
640       case 1:
641         EXPECT_EQ(0u, root->lost_output_surface_count());
642         EXPECT_EQ(0u, child->lost_output_surface_count());
643         EXPECT_EQ(0u, grandchild->lost_output_surface_count());
644         // Lose the context and struggle to recreate it.
645         LoseContext();
646         times_to_fail_create_ = 1;
647         break;
648       case 2:
649         EXPECT_GE(1u, root->lost_output_surface_count());
650         EXPECT_GE(1u, child->lost_output_surface_count());
651         EXPECT_GE(1u, grandchild->lost_output_surface_count());
652         EndTest();
653         break;
654       default:
655         NOTREACHED();
656     }
657   }
658
659   virtual void AfterTest() OVERRIDE {}
660
661  private:
662   int num_commits_;
663
664   FakeContentLayerClient client_;
665   scoped_refptr<FakeContentLayer> root_;
666   scoped_refptr<FakeContentLayer> child_;
667   scoped_refptr<FakeContentLayer> grandchild_;
668 };
669
670 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
671
672 class LayerTreeHostContextTestDontUseLostResources
673     : public LayerTreeHostContextTest {
674  public:
675   LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
676     context_should_support_io_surface_ = true;
677
678     child_output_surface_ = FakeOutputSurface::Create3d();
679     child_output_surface_->BindToClient(&output_surface_client_);
680     shared_bitmap_manager_.reset(new TestSharedBitmapManager());
681     child_resource_provider_ = ResourceProvider::Create(
682         child_output_surface_.get(), shared_bitmap_manager_.get(), 0, false, 1,
683         false);
684   }
685
686   static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
687
688   virtual void SetupTree() OVERRIDE {
689     gpu::gles2::GLES2Interface* gl =
690         child_output_surface_->context_provider()->ContextGL();
691
692     scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
693
694     scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
695     pass_for_quad->SetNew(
696         // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
697         RenderPass::Id(2, 1),
698         gfx::Rect(0, 0, 10, 10),
699         gfx::Rect(0, 0, 10, 10),
700         gfx::Transform());
701
702     scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
703     pass->SetNew(RenderPass::Id(1, 1),
704                  gfx::Rect(0, 0, 10, 10),
705                  gfx::Rect(0, 0, 10, 10),
706                  gfx::Transform());
707     pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
708                                    RenderPass::Id(2, 1));
709
710     frame_data->render_pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
711     frame_data->render_pass_list.push_back(pass.PassAs<RenderPass>());
712
713     delegated_resource_collection_ = new DelegatedFrameResourceCollection;
714     delegated_frame_provider_ = new DelegatedFrameProvider(
715         delegated_resource_collection_.get(), frame_data.Pass());
716
717     ResourceProvider::ResourceId resource =
718         child_resource_provider_->CreateResource(
719             gfx::Size(4, 4),
720             GL_CLAMP_TO_EDGE,
721             ResourceProvider::TextureUsageAny,
722             RGBA_8888);
723     ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
724                                              resource);
725
726     gpu::Mailbox mailbox;
727     gl->GenMailboxCHROMIUM(mailbox.name);
728     GLuint sync_point = gl->InsertSyncPointCHROMIUM();
729
730     scoped_refptr<Layer> root = Layer::Create();
731     root->SetBounds(gfx::Size(10, 10));
732     root->SetAnchorPoint(gfx::PointF());
733     root->SetIsDrawable(true);
734
735     scoped_refptr<FakeDelegatedRendererLayer> delegated =
736         FakeDelegatedRendererLayer::Create(delegated_frame_provider_.get());
737     delegated->SetBounds(gfx::Size(10, 10));
738     delegated->SetAnchorPoint(gfx::PointF());
739     delegated->SetIsDrawable(true);
740     root->AddChild(delegated);
741
742     scoped_refptr<ContentLayer> content = ContentLayer::Create(&client_);
743     content->SetBounds(gfx::Size(10, 10));
744     content->SetAnchorPoint(gfx::PointF());
745     content->SetIsDrawable(true);
746     root->AddChild(content);
747
748     scoped_refptr<TextureLayer> texture = TextureLayer::CreateForMailbox(NULL);
749     texture->SetBounds(gfx::Size(10, 10));
750     texture->SetAnchorPoint(gfx::PointF());
751     texture->SetIsDrawable(true);
752     texture->SetTextureMailbox(
753         TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
754         SingleReleaseCallback::Create(
755             base::Bind(&LayerTreeHostContextTestDontUseLostResources::
756                             EmptyReleaseCallback)));
757     root->AddChild(texture);
758
759     scoped_refptr<ContentLayer> mask = ContentLayer::Create(&client_);
760     mask->SetBounds(gfx::Size(10, 10));
761     mask->SetAnchorPoint(gfx::PointF());
762
763     scoped_refptr<ContentLayer> content_with_mask =
764         ContentLayer::Create(&client_);
765     content_with_mask->SetBounds(gfx::Size(10, 10));
766     content_with_mask->SetAnchorPoint(gfx::PointF());
767     content_with_mask->SetIsDrawable(true);
768     content_with_mask->SetMaskLayer(mask.get());
769     root->AddChild(content_with_mask);
770
771     scoped_refptr<VideoLayer> video_color =
772         VideoLayer::Create(&color_frame_provider_);
773     video_color->SetBounds(gfx::Size(10, 10));
774     video_color->SetAnchorPoint(gfx::PointF());
775     video_color->SetIsDrawable(true);
776     root->AddChild(video_color);
777
778     scoped_refptr<VideoLayer> video_hw =
779         VideoLayer::Create(&hw_frame_provider_);
780     video_hw->SetBounds(gfx::Size(10, 10));
781     video_hw->SetAnchorPoint(gfx::PointF());
782     video_hw->SetIsDrawable(true);
783     root->AddChild(video_hw);
784
785     scoped_refptr<VideoLayer> video_scaled_hw =
786         VideoLayer::Create(&scaled_hw_frame_provider_);
787     video_scaled_hw->SetBounds(gfx::Size(10, 10));
788     video_scaled_hw->SetAnchorPoint(gfx::PointF());
789     video_scaled_hw->SetIsDrawable(true);
790     root->AddChild(video_scaled_hw);
791
792     color_video_frame_ = VideoFrame::CreateColorFrame(
793         gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
794     hw_video_frame_ =
795         VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
796                                           mailbox, GL_TEXTURE_2D, sync_point)),
797                                       media::VideoFrame::ReleaseMailboxCB(),
798                                       gfx::Size(4, 4),
799                                       gfx::Rect(0, 0, 4, 4),
800                                       gfx::Size(4, 4),
801                                       base::TimeDelta(),
802                                       VideoFrame::ReadPixelsCB());
803     scaled_hw_video_frame_ =
804         VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
805                                           mailbox, GL_TEXTURE_2D, sync_point)),
806                                       media::VideoFrame::ReleaseMailboxCB(),
807                                       gfx::Size(4, 4),
808                                       gfx::Rect(0, 0, 3, 2),
809                                       gfx::Size(4, 4),
810                                       base::TimeDelta(),
811                                       VideoFrame::ReadPixelsCB());
812
813     color_frame_provider_.set_frame(color_video_frame_);
814     hw_frame_provider_.set_frame(hw_video_frame_);
815     scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
816
817     if (!delegating_renderer()) {
818       // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
819       scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
820       io_surface->SetBounds(gfx::Size(10, 10));
821       io_surface->SetAnchorPoint(gfx::PointF());
822       io_surface->SetIsDrawable(true);
823       io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10));
824       root->AddChild(io_surface);
825     }
826
827     // Enable the hud.
828     LayerTreeDebugState debug_state;
829     debug_state.show_property_changed_rects = true;
830     layer_tree_host()->SetDebugState(debug_state);
831
832     scoped_refptr<PaintedScrollbarLayer> scrollbar =
833         PaintedScrollbarLayer::Create(
834             scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), content->id());
835     scrollbar->SetBounds(gfx::Size(10, 10));
836     scrollbar->SetAnchorPoint(gfx::PointF());
837     scrollbar->SetIsDrawable(true);
838     root->AddChild(scrollbar);
839
840     layer_tree_host()->SetRootLayer(root);
841     LayerTreeHostContextTest::SetupTree();
842   }
843
844   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
845
846   virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
847     LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
848
849     if (host_impl->active_tree()->source_frame_number() == 3) {
850       // On the third commit we're recovering from context loss. Hardware
851       // video frames should not be reused by the VideoFrameProvider, but
852       // software frames can be.
853       hw_frame_provider_.set_frame(NULL);
854       scaled_hw_frame_provider_.set_frame(NULL);
855     }
856   }
857
858   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
859       LayerTreeHostImpl* host_impl,
860       LayerTreeHostImpl::FrameData* frame,
861       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
862     if (host_impl->active_tree()->source_frame_number() == 2) {
863       // Lose the context during draw on the second commit. This will cause
864       // a third commit to recover.
865       context3d_->set_times_bind_texture_succeeds(0);
866     }
867     return draw_result;
868   }
869
870   virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
871       OVERRIDE {
872     // This will get called twice:
873     // First when we create the initial output surface...
874     if (layer_tree_host()->source_frame_number() > 0) {
875       // ... and then again after we forced the context to be lost.
876       lost_context_ = true;
877     }
878     return LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
879   }
880
881   virtual void DidCommitAndDrawFrame() OVERRIDE {
882     ASSERT_TRUE(layer_tree_host()->hud_layer());
883     // End the test once we know the 3nd frame drew.
884     if (layer_tree_host()->source_frame_number() < 5) {
885       layer_tree_host()->root_layer()->SetNeedsDisplay();
886       layer_tree_host()->SetNeedsCommit();
887     } else {
888       EndTest();
889     }
890   }
891
892   virtual void AfterTest() OVERRIDE { EXPECT_TRUE(lost_context_); }
893
894  private:
895   FakeContentLayerClient client_;
896   bool lost_context_;
897
898   FakeOutputSurfaceClient output_surface_client_;
899   scoped_ptr<FakeOutputSurface> child_output_surface_;
900   scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
901   scoped_ptr<ResourceProvider> child_resource_provider_;
902
903   scoped_refptr<DelegatedFrameResourceCollection>
904       delegated_resource_collection_;
905   scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
906
907   scoped_refptr<VideoFrame> color_video_frame_;
908   scoped_refptr<VideoFrame> hw_video_frame_;
909   scoped_refptr<VideoFrame> scaled_hw_video_frame_;
910
911   FakeVideoFrameProvider color_frame_provider_;
912   FakeVideoFrameProvider hw_frame_provider_;
913   FakeVideoFrameProvider scaled_hw_frame_provider_;
914 };
915
916 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
917
918 class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
919     : public LayerTreeHostContextTest {
920  public:
921   virtual void BeginTest() OVERRIDE {
922     // This must be called immediately after creating LTH, before the first
923     // OutputSurface is initialized.
924     ASSERT_TRUE(layer_tree_host()->output_surface_lost());
925
926     times_output_surface_created_ = 0;
927
928     // Post the SetNeedsCommit before the readback to make sure it is run
929     // on the main thread before the readback's replacement commit when
930     // we have a threaded compositor.
931     PostSetNeedsCommitToMainThread();
932
933     char pixels[4];
934     bool result =
935         layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(1, 1));
936     EXPECT_EQ(!delegating_renderer(), result);
937     EXPECT_EQ(1, times_output_surface_created_);
938   }
939
940   virtual void DidInitializeOutputSurface() OVERRIDE {
941     ++times_output_surface_created_;
942   }
943
944   virtual void DidCommitAndDrawFrame() OVERRIDE { EndTest(); }
945
946   virtual void AfterTest() OVERRIDE {
947     // Should not try to create output surface again after successfully
948     // created by CompositeAndReadback.
949     EXPECT_EQ(1, times_output_surface_created_);
950   }
951
952   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
953       LayerTreeHostImpl* host_impl,
954       LayerTreeHostImpl::FrameData* frame_data,
955       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
956     EXPECT_GE(host_impl->active_tree()->source_frame_number(), 0);
957     EXPECT_LE(host_impl->active_tree()->source_frame_number(), 1);
958     return draw_result;
959   }
960
961   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
962     // We should only draw for the readback and the replacement commit.
963     // The replacement commit will also be the first commit after output
964     // surface initialization.
965     EXPECT_GE(host_impl->active_tree()->source_frame_number(), 0);
966     EXPECT_LE(host_impl->active_tree()->source_frame_number(), 1);
967   }
968
969   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
970                                    bool result) OVERRIDE {
971     // We should only swap for the replacement commit.
972     EXPECT_EQ(host_impl->active_tree()->source_frame_number(), 1);
973     EndTest();
974   }
975
976  private:
977   int times_output_surface_created_;
978 };
979
980 SINGLE_AND_MULTI_THREAD_TEST_F(
981     LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit);
982
983 // This test verifies that losing an output surface during a
984 // simultaneous readback and forced redraw works and does not deadlock.
985 class LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw
986     : public LayerTreeHostContextTest {
987  protected:
988   static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
989   static const int kReadbackSourceFrameNumber = 1;
990   static const int kReadbackReplacementSourceFrameNumber = 2;
991   static const int kSecondOutputSurfaceInitSourceFrameNumber = 3;
992
993   LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw()
994       : did_react_to_first_commit_(false) {}
995
996   virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
997     // This enables forced draws after a single prepare to draw failure.
998     settings->timeout_and_draw_when_animation_checkerboards = true;
999     settings->maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
1000   }
1001
1002   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1003
1004   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1005       LayerTreeHostImpl* host_impl,
1006       LayerTreeHostImpl::FrameData* frame_data,
1007       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1008     int sfn = host_impl->active_tree()->source_frame_number();
1009     EXPECT_TRUE(sfn == kFirstOutputSurfaceInitSourceFrameNumber ||
1010                 sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1011                 sfn == kReadbackSourceFrameNumber)
1012         << sfn;
1013
1014     // Before we react to the failed draw by initiating the forced draw
1015     // sequence, start a readback on the main thread and then lose the context
1016     // to start output surface initialization all at the same time.
1017     if (sfn == kFirstOutputSurfaceInitSourceFrameNumber &&
1018         !did_react_to_first_commit_) {
1019       did_react_to_first_commit_ = true;
1020       PostReadbackToMainThread();
1021       LoseContext();
1022     }
1023
1024     return DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
1025   }
1026
1027   virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
1028                                            bool success) OVERRIDE {
1029     // -1 is for the first output surface initialization.
1030     int sfn = host_impl->active_tree()->source_frame_number();
1031     EXPECT_TRUE(sfn == -1 || sfn == kReadbackReplacementSourceFrameNumber)
1032         << sfn;
1033   }
1034
1035   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1036     // We should only draw the first commit after output surface initialization
1037     // and attempt to draw the readback commit (which will fail).
1038     // All others should abort because the output surface is lost.
1039     int sfn = host_impl->active_tree()->source_frame_number();
1040     EXPECT_TRUE(sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1041                 sfn == kReadbackSourceFrameNumber)
1042         << sfn;
1043   }
1044
1045   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1046                                    bool result) OVERRIDE {
1047     // We should only swap the first commit after the second output surface
1048     // initialization.
1049     int sfn = host_impl->active_tree()->source_frame_number();
1050     EXPECT_TRUE(sfn == kSecondOutputSurfaceInitSourceFrameNumber) << sfn;
1051     EndTest();
1052   }
1053
1054   virtual void AfterTest() OVERRIDE {}
1055
1056   int did_react_to_first_commit_;
1057 };
1058
1059 MULTI_THREAD_TEST_F(
1060     LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw);
1061
1062 // This test verifies that losing an output surface right before a
1063 // simultaneous readback and forced redraw works and does not deadlock.
1064 class LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit
1065     : public LayerTreeHostContextTest {
1066  protected:
1067   static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
1068   static const int kReadbackSourceFrameNumber = 1;
1069   static const int kForcedDrawCommitSourceFrameNumber = 2;
1070   static const int kSecondOutputSurfaceInitSourceFrameNumber = 2;
1071
1072   LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit()
1073       : did_lose_context_(false) {}
1074
1075   virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1076     // This enables forced draws after a single prepare to draw failure.
1077     settings->timeout_and_draw_when_animation_checkerboards = true;
1078     settings->maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
1079   }
1080
1081   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1082
1083   virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1084       LayerTreeHostImpl* host_impl,
1085       LayerTreeHostImpl::FrameData* frame_data,
1086       DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1087     int sfn = host_impl->active_tree()->source_frame_number();
1088     EXPECT_TRUE(sfn == kFirstOutputSurfaceInitSourceFrameNumber ||
1089                 sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1090                 sfn == kReadbackSourceFrameNumber)
1091         << sfn;
1092
1093     // Before we react to the failed draw by initiating the forced draw
1094     // sequence, start a readback on the main thread and then lose the context
1095     // to start output surface initialization all at the same time.
1096     if (sfn == kFirstOutputSurfaceInitSourceFrameNumber && !did_lose_context_) {
1097       did_lose_context_ = true;
1098       LoseContext();
1099     }
1100
1101     // Returning false will result in a forced draw.
1102     return DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
1103   }
1104
1105   virtual void DidInitializeOutputSurface() OVERRIDE {
1106     if (layer_tree_host()->source_frame_number() > 0) {
1107       // Perform a readback right after the second output surface
1108       // initialization.
1109       char pixels[4];
1110       layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
1111     }
1112   }
1113
1114   virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
1115                                            bool success) OVERRIDE {
1116     // -1 is for the first output surface initialization.
1117     int sfn = host_impl->active_tree()->source_frame_number();
1118     EXPECT_TRUE(sfn == -1 || sfn == kFirstOutputSurfaceInitSourceFrameNumber)
1119         << sfn;
1120   }
1121
1122   virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1123     // We should only draw the first commit after output surface initialization
1124     // and attempt to draw the readback commit (which will fail).
1125     // All others should abort because the output surface is lost.
1126     int sfn = host_impl->active_tree()->source_frame_number();
1127     EXPECT_TRUE(sfn == kForcedDrawCommitSourceFrameNumber ||
1128                 sfn == kReadbackSourceFrameNumber)
1129         << sfn;
1130   }
1131
1132   virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1133                                    bool result) OVERRIDE {
1134     // We should only swap the first commit after the second output surface
1135     // initialization.
1136     int sfn = host_impl->active_tree()->source_frame_number();
1137     EXPECT_TRUE(sfn == kForcedDrawCommitSourceFrameNumber) << sfn;
1138     EndTest();
1139   }
1140
1141   virtual void AfterTest() OVERRIDE {}
1142
1143   int did_lose_context_;
1144 };
1145
1146 MULTI_THREAD_TEST_F(
1147     LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit);
1148
1149 class ImplSidePaintingLayerTreeHostContextTest
1150     : public LayerTreeHostContextTest {
1151  public:
1152   virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1153     settings->impl_side_painting = true;
1154   }
1155 };
1156
1157 class LayerTreeHostContextTestImplSidePainting
1158     : public ImplSidePaintingLayerTreeHostContextTest {
1159  public:
1160   virtual void SetupTree() OVERRIDE {
1161     scoped_refptr<Layer> root = Layer::Create();
1162     root->SetBounds(gfx::Size(10, 10));
1163     root->SetAnchorPoint(gfx::PointF());
1164     root->SetIsDrawable(true);
1165
1166     scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
1167     picture->SetBounds(gfx::Size(10, 10));
1168     picture->SetAnchorPoint(gfx::PointF());
1169     picture->SetIsDrawable(true);
1170     root->AddChild(picture);
1171
1172     layer_tree_host()->SetRootLayer(root);
1173     LayerTreeHostContextTest::SetupTree();
1174   }
1175
1176   virtual void BeginTest() OVERRIDE {
1177     times_to_lose_during_commit_ = 1;
1178     PostSetNeedsCommitToMainThread();
1179   }
1180
1181   virtual void AfterTest() OVERRIDE {}
1182
1183   virtual void DidInitializeOutputSurface() OVERRIDE { EndTest(); }
1184
1185  private:
1186   FakeContentLayerClient client_;
1187 };
1188
1189 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
1190
1191 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1192  public:
1193   ScrollbarLayerLostContext() : commits_(0) {}
1194
1195   virtual void BeginTest() OVERRIDE {
1196     scoped_refptr<Layer> scroll_layer = Layer::Create();
1197     scrollbar_layer_ =
1198         FakePaintedScrollbarLayer::Create(false, true, scroll_layer->id());
1199     scrollbar_layer_->SetBounds(gfx::Size(10, 100));
1200     layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
1201     layer_tree_host()->root_layer()->AddChild(scroll_layer);
1202     PostSetNeedsCommitToMainThread();
1203   }
1204
1205   virtual void AfterTest() OVERRIDE {}
1206
1207   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1208     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1209
1210     ++commits_;
1211     switch (commits_) {
1212       case 1:
1213         // First (regular) update, we should upload 2 resources (thumb, and
1214         // backtrack).
1215         EXPECT_EQ(1, scrollbar_layer_->update_count());
1216         LoseContext();
1217         break;
1218       case 2:
1219         // Second update, after the lost context, we should still upload 2
1220         // resources even if the contents haven't changed.
1221         EXPECT_EQ(2, scrollbar_layer_->update_count());
1222         EndTest();
1223         break;
1224       case 3:
1225         // Single thread proxy issues extra commits after context lost.
1226         // http://crbug.com/287250
1227         if (HasImplThread())
1228           NOTREACHED();
1229         break;
1230       default:
1231         NOTREACHED();
1232     }
1233   }
1234
1235  private:
1236   int commits_;
1237   scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
1238 };
1239
1240 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1241
1242 class UIResourceLostTest : public LayerTreeHostContextTest {
1243  public:
1244   UIResourceLostTest() : time_step_(0) {}
1245   virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1246     settings->texture_id_allocation_chunk_size = 1;
1247   }
1248   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1249   virtual void AfterTest() OVERRIDE {}
1250
1251   // This is called on the main thread after each commit and
1252   // DidActivateTreeOnThread, with the value of time_step_ at the time
1253   // of the call to DidActivateTreeOnThread. Similar tests will do
1254   // work on the main thread in DidCommit but that is unsuitable because
1255   // the main thread work for these tests must happen after
1256   // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1257   // painting.
1258   virtual void StepCompleteOnMainThread(int time_step) = 0;
1259
1260   // Called after DidActivateTreeOnThread. If this is done during the commit,
1261   // the call to StepCompleteOnMainThread will not occur until after
1262   // the commit completes, because the main thread is blocked.
1263   void PostStepCompleteToMainThread() {
1264     proxy()->MainThreadTaskRunner()->PostTask(
1265         FROM_HERE,
1266         base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal,
1267                    base::Unretained(this),
1268                    time_step_));
1269   }
1270
1271   void PostLoseContextToImplThread() {
1272     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1273     base::SingleThreadTaskRunner* task_runner =
1274         HasImplThread() ? ImplThreadTaskRunner()
1275                         : base::MessageLoopProxy::current();
1276     task_runner->PostTask(FROM_HERE,
1277                           base::Bind(&LayerTreeHostContextTest::LoseContext,
1278                                      base::Unretained(this)));
1279   }
1280
1281  protected:
1282   int time_step_;
1283   scoped_ptr<FakeScopedUIResource> ui_resource_;
1284
1285  private:
1286   void StepCompleteOnMainThreadInternal(int step) {
1287     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1288     StepCompleteOnMainThread(step);
1289   }
1290 };
1291
1292 class UIResourceLostTestSimple : public UIResourceLostTest {
1293  public:
1294   // This is called when the commit is complete and the new layer tree has been
1295   // activated.
1296   virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1297
1298   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1299     if (!layer_tree_host()->settings().impl_side_painting) {
1300       StepCompleteOnImplThread(impl);
1301       PostStepCompleteToMainThread();
1302       ++time_step_;
1303     }
1304   }
1305
1306   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1307     if (layer_tree_host()->settings().impl_side_painting) {
1308       StepCompleteOnImplThread(impl);
1309       PostStepCompleteToMainThread();
1310       ++time_step_;
1311     }
1312   }
1313 };
1314
1315 // Losing context after an UI resource has been created.
1316 class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
1317  public:
1318   virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1319     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1320     switch (step) {
1321       case 0:
1322         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1323         // Expects a valid UIResourceId.
1324         EXPECT_NE(0, ui_resource_->id());
1325         PostSetNeedsCommitToMainThread();
1326         break;
1327       case 4:
1328         // Release resource before ending the test.
1329         ui_resource_.reset();
1330         EndTest();
1331         break;
1332       case 5:
1333         // Single thread proxy issues extra commits after context lost.
1334         // http://crbug.com/287250
1335         if (HasImplThread())
1336           NOTREACHED();
1337         break;
1338       case 6:
1339         NOTREACHED();
1340     }
1341   }
1342
1343   virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1344     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1345     switch (time_step_) {
1346       case 1:
1347         // The resource should have been created on LTHI after the commit.
1348         EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1349         PostSetNeedsCommitToMainThread();
1350         break;
1351       case 2:
1352         LoseContext();
1353         break;
1354       case 3:
1355         // The resources should have been recreated. The bitmap callback should
1356         // have been called once with the resource_lost flag set to true.
1357         EXPECT_EQ(1, ui_resource_->lost_resource_count);
1358         // Resource Id on the impl-side have been recreated as well. Note
1359         // that the same UIResourceId persists after the context lost.
1360         EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1361         PostSetNeedsCommitToMainThread();
1362         break;
1363     }
1364   }
1365 };
1366
1367 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
1368
1369 // Losing context before UI resource requests can be commited.  Three sequences
1370 // of creation/deletion are considered:
1371 // 1. Create one resource -> Context Lost => Expect the resource to have been
1372 // created.
1373 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1374 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1375 // test_id1_ to have been created.
1376 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1377 // the resource to not exist in the manager.
1378 class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
1379  public:
1380   UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1381
1382   virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1383     switch (step) {
1384       case 0:
1385         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1386         // Lose the context on the impl thread before the commit.
1387         PostLoseContextToImplThread();
1388         break;
1389       case 2:
1390         // Sequence 2:
1391         // Currently one resource has been created.
1392         test_id0_ = ui_resource_->id();
1393         // Delete this resource.
1394         ui_resource_.reset();
1395         // Create another resource.
1396         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1397         test_id1_ = ui_resource_->id();
1398         // Sanity check that two resource creations return different ids.
1399         EXPECT_NE(test_id0_, test_id1_);
1400         // Lose the context on the impl thread before the commit.
1401         PostLoseContextToImplThread();
1402         break;
1403       case 3:
1404         // Clear the manager of resources.
1405         ui_resource_.reset();
1406         PostSetNeedsCommitToMainThread();
1407         break;
1408       case 4:
1409         // Sequence 3:
1410         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1411         test_id0_ = ui_resource_->id();
1412         // Sanity check the UIResourceId should not be 0.
1413         EXPECT_NE(0, test_id0_);
1414         // Usually ScopedUIResource are deleted from the manager in their
1415         // destructor (so usually ui_resource_.reset()).  But here we need
1416         // ui_resource_ for the next step, so call DeleteUIResource directly.
1417         layer_tree_host()->DeleteUIResource(test_id0_);
1418         // Delete the resouce and then lose the context.
1419         PostLoseContextToImplThread();
1420         break;
1421       case 5:
1422         // Release resource before ending the test.
1423         ui_resource_.reset();
1424         EndTest();
1425         break;
1426       case 6:
1427         // Single thread proxy issues extra commits after context lost.
1428         // http://crbug.com/287250
1429         if (HasImplThread())
1430           NOTREACHED();
1431         break;
1432       case 8:
1433         NOTREACHED();
1434     }
1435   }
1436
1437   virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1438     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1439     switch (time_step_) {
1440       case 1:
1441         // Sequence 1 (continued):
1442         // The first context lost happens before the resources were created,
1443         // and because it resulted in no resources being destroyed, it does not
1444         // trigger resource re-creation.
1445         EXPECT_EQ(1, ui_resource_->resource_create_count);
1446         EXPECT_EQ(0, ui_resource_->lost_resource_count);
1447         // Resource Id on the impl-side has been created.
1448         PostSetNeedsCommitToMainThread();
1449         break;
1450       case 3:
1451         // Sequence 2 (continued):
1452         // The previous resource should have been deleted.
1453         EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1454         if (HasImplThread()) {
1455           // The second resource should have been created.
1456           EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
1457         } else {
1458           // The extra commit that happens at context lost in the single thread
1459           // proxy changes the timing so that the resource has been destroyed.
1460           // http://crbug.com/287250
1461           EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id1_));
1462         }
1463         // The second resource called the resource callback once and since the
1464         // context is lost, a "resource lost" callback was also issued.
1465         EXPECT_EQ(2, ui_resource_->resource_create_count);
1466         EXPECT_EQ(1, ui_resource_->lost_resource_count);
1467         break;
1468       case 5:
1469         // Sequence 3 (continued):
1470         // Expect the resource callback to have been called once.
1471         EXPECT_EQ(1, ui_resource_->resource_create_count);
1472         // No "resource lost" callbacks.
1473         EXPECT_EQ(0, ui_resource_->lost_resource_count);
1474         // The UI resource id should not be valid
1475         EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1476         break;
1477     }
1478   }
1479
1480  private:
1481   UIResourceId test_id0_;
1482   UIResourceId test_id1_;
1483 };
1484
1485 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
1486
1487 // Losing UI resource before the pending trees is activated but after the
1488 // commit.  Impl-side-painting only.
1489 class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
1490   virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1491     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1492     switch (step) {
1493       case 0:
1494         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1495         PostSetNeedsCommitToMainThread();
1496         break;
1497       case 3:
1498         test_id_ = ui_resource_->id();
1499         ui_resource_.reset();
1500         PostSetNeedsCommitToMainThread();
1501         break;
1502       case 5:
1503         // Release resource before ending the test.
1504         ui_resource_.reset();
1505         EndTest();
1506         break;
1507       case 6:
1508         // Make sure no extra commits happened.
1509         NOTREACHED();
1510     }
1511   }
1512
1513   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1514     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1515     switch (time_step_) {
1516       case 2:
1517         PostSetNeedsCommitToMainThread();
1518         break;
1519       case 4:
1520         PostSetNeedsCommitToMainThread();
1521         break;
1522     }
1523   }
1524
1525   virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1526     switch (time_step_) {
1527       case 1:
1528         // The resource creation callback has been called.
1529         EXPECT_EQ(1, ui_resource_->resource_create_count);
1530         // The resource is not yet lost (sanity check).
1531         EXPECT_EQ(0, ui_resource_->lost_resource_count);
1532         // The resource should not have been created yet on the impl-side.
1533         EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1534         LoseContext();
1535         break;
1536       case 3:
1537         LoseContext();
1538         break;
1539     }
1540   }
1541
1542   virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1543     LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1544     switch (time_step_) {
1545       case 1:
1546         // The pending requests on the impl-side should have been processed.
1547         EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1548         break;
1549       case 2:
1550         // The "lost resource" callback should have been called once.
1551         EXPECT_EQ(1, ui_resource_->lost_resource_count);
1552         break;
1553       case 4:
1554         // The resource is deleted and should not be in the manager.  Use
1555         // test_id_ since ui_resource_ has been deleted.
1556         EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
1557         break;
1558     }
1559
1560     PostStepCompleteToMainThread();
1561     ++time_step_;
1562   }
1563
1564  private:
1565   UIResourceId test_id_;
1566 };
1567
1568 TEST_F(UIResourceLostBeforeActivateTree,
1569        RunMultiThread_DirectRenderer_ImplSidePaint) {
1570   RunTest(true, false, true);
1571 }
1572
1573 TEST_F(UIResourceLostBeforeActivateTree,
1574        RunMultiThread_DelegatingRenderer_ImplSidePaint) {
1575   RunTest(true, true, true);
1576 }
1577
1578 // Resources evicted explicitly and by visibility changes.
1579 class UIResourceLostEviction : public UIResourceLostTestSimple {
1580  public:
1581   virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1582     EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1583     switch (step) {
1584       case 0:
1585         ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1586         EXPECT_NE(0, ui_resource_->id());
1587         PostSetNeedsCommitToMainThread();
1588         break;
1589       case 2:
1590         // Make the tree not visible.
1591         PostSetVisibleToMainThread(false);
1592         break;
1593       case 3:
1594         // Release resource before ending the test.
1595         ui_resource_.reset();
1596         EndTest();
1597         break;
1598       case 4:
1599         NOTREACHED();
1600     }
1601   }
1602
1603   virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl,
1604                                        bool visible) OVERRIDE {
1605     TestWebGraphicsContext3D* context = TestContext();
1606     if (!visible) {
1607       // All resources should have been evicted.
1608       ASSERT_EQ(0u, context->NumTextures());
1609       EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1610       EXPECT_EQ(2, ui_resource_->resource_create_count);
1611       EXPECT_EQ(1, ui_resource_->lost_resource_count);
1612       // Drawing is disabled both because of the evicted resources and
1613       // because the renderer is not visible.
1614       EXPECT_FALSE(impl->CanDraw());
1615       // Make the renderer visible again.
1616       PostSetVisibleToMainThread(true);
1617     }
1618   }
1619
1620   virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1621     TestWebGraphicsContext3D* context = TestContext();
1622     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1623     switch (time_step_) {
1624       case 1:
1625         // The resource should have been created on LTHI after the commit.
1626         ASSERT_EQ(1u, context->NumTextures());
1627         EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1628         EXPECT_EQ(1, ui_resource_->resource_create_count);
1629         EXPECT_EQ(0, ui_resource_->lost_resource_count);
1630         EXPECT_TRUE(impl->CanDraw());
1631         // Evict all UI resources. This will trigger a commit.
1632         impl->EvictAllUIResources();
1633         ASSERT_EQ(0u, context->NumTextures());
1634         EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1635         EXPECT_EQ(1, ui_resource_->resource_create_count);
1636         EXPECT_EQ(0, ui_resource_->lost_resource_count);
1637         EXPECT_FALSE(impl->CanDraw());
1638         break;
1639       case 2:
1640         // The resource should have been recreated.
1641         ASSERT_EQ(1u, context->NumTextures());
1642         EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1643         EXPECT_EQ(2, ui_resource_->resource_create_count);
1644         EXPECT_EQ(1, ui_resource_->lost_resource_count);
1645         EXPECT_TRUE(impl->CanDraw());
1646         break;
1647       case 3:
1648         // The resource should have been recreated after visibility was
1649         // restored.
1650         ASSERT_EQ(1u, context->NumTextures());
1651         EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1652         EXPECT_EQ(3, ui_resource_->resource_create_count);
1653         EXPECT_EQ(2, ui_resource_->lost_resource_count);
1654         EXPECT_TRUE(impl->CanDraw());
1655         break;
1656     }
1657   }
1658 };
1659
1660 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1661
1662 class LayerTreeHostContextTestSurfaceCreateCallback
1663     : public LayerTreeHostContextTest {
1664  public:
1665   LayerTreeHostContextTestSurfaceCreateCallback()
1666       : LayerTreeHostContextTest(),
1667         layer_(FakeContentLayer::Create(&client_)) {}
1668
1669   virtual void SetupTree() OVERRIDE {
1670     layer_->SetBounds(gfx::Size(10, 20));
1671     layer_tree_host()->SetRootLayer(layer_);
1672     LayerTreeHostContextTest::SetupTree();
1673   }
1674
1675   virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1676
1677   virtual void DidCommit() OVERRIDE {
1678     switch (layer_tree_host()->source_frame_number()) {
1679       case 1:
1680         EXPECT_EQ(1u, layer_->output_surface_created_count());
1681         layer_tree_host()->SetNeedsCommit();
1682         break;
1683       case 2:
1684         EXPECT_EQ(1u, layer_->output_surface_created_count());
1685         layer_tree_host()->SetNeedsCommit();
1686         break;
1687       case 3:
1688         EXPECT_EQ(1u, layer_->output_surface_created_count());
1689         break;
1690       case 4:
1691         EXPECT_EQ(2u, layer_->output_surface_created_count());
1692         layer_tree_host()->SetNeedsCommit();
1693         break;
1694     }
1695   }
1696
1697   virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1698     LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1699     switch (LastCommittedSourceFrameNumber(impl)) {
1700       case 0:
1701         break;
1702       case 1:
1703         break;
1704       case 2:
1705         LoseContext();
1706         break;
1707       case 3:
1708         EndTest();
1709         break;
1710     }
1711   }
1712
1713   virtual void AfterTest() OVERRIDE {}
1714
1715  protected:
1716   FakeContentLayerClient client_;
1717   scoped_refptr<FakeContentLayer> layer_;
1718 };
1719
1720 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
1721
1722 }  // namespace
1723 }  // namespace cc