Task Manager: Remove goat teleporter.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_context.cc
blob0e15071458f3842a22cbe1913183b66eeacbc1bc
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.
5 #include "cc/trees/layer_tree_host.h"
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/resources/single_release_callback.h"
22 #include "cc/test/fake_content_layer.h"
23 #include "cc/test/fake_content_layer_client.h"
24 #include "cc/test/fake_content_layer_impl.h"
25 #include "cc/test/fake_delegated_renderer_layer.h"
26 #include "cc/test/fake_delegated_renderer_layer_impl.h"
27 #include "cc/test/fake_layer_tree_host_client.h"
28 #include "cc/test/fake_output_surface.h"
29 #include "cc/test/fake_output_surface_client.h"
30 #include "cc/test/fake_painted_scrollbar_layer.h"
31 #include "cc/test/fake_scoped_ui_resource.h"
32 #include "cc/test/fake_scrollbar.h"
33 #include "cc/test/fake_video_frame_provider.h"
34 #include "cc/test/layer_tree_test.h"
35 #include "cc/test/render_pass_test_common.h"
36 #include "cc/test/test_context_provider.h"
37 #include "cc/test/test_shared_bitmap_manager.h"
38 #include "cc/test/test_web_graphics_context_3d.h"
39 #include "cc/trees/layer_tree_host_impl.h"
40 #include "cc/trees/layer_tree_impl.h"
41 #include "cc/trees/single_thread_proxy.h"
42 #include "gpu/GLES2/gl2extchromium.h"
43 #include "media/base/media.h"
45 using media::VideoFrame;
47 namespace cc {
48 namespace {
50 // These tests deal with losing the 3d graphics context.
51 class LayerTreeHostContextTest : public LayerTreeTest {
52 public:
53 LayerTreeHostContextTest()
54 : LayerTreeTest(),
55 context3d_(NULL),
56 times_to_fail_create_(0),
57 times_to_lose_during_commit_(0),
58 times_to_lose_during_draw_(0),
59 times_to_fail_recreate_(0),
60 times_to_expect_create_failed_(0),
61 times_create_failed_(0),
62 committed_at_least_once_(false),
63 context_should_support_io_surface_(false),
64 fallback_context_works_(false) {
65 media::InitializeMediaLibraryForTesting();
68 void LoseContext() {
69 // For sanity-checking tests, they should only call this when the
70 // context is not lost.
71 CHECK(context3d_);
72 context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
73 GL_INNOCENT_CONTEXT_RESET_ARB);
74 context3d_ = NULL;
77 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
78 return TestWebGraphicsContext3D::Create();
81 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
82 OVERRIDE {
83 if (times_to_fail_create_) {
84 --times_to_fail_create_;
85 ExpectCreateToFail();
86 return scoped_ptr<FakeOutputSurface>();
89 scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
90 context3d_ = context3d.get();
92 if (context_should_support_io_surface_) {
93 context3d_->set_have_extension_io_surface(true);
94 context3d_->set_have_extension_egl_image(true);
97 if (delegating_renderer())
98 return FakeOutputSurface::CreateDelegating3d(context3d.Pass());
99 else
100 return FakeOutputSurface::Create3d(context3d.Pass());
103 virtual DrawResult PrepareToDrawOnThread(
104 LayerTreeHostImpl* host_impl,
105 LayerTreeHostImpl::FrameData* frame,
106 DrawResult draw_result) OVERRIDE {
107 EXPECT_EQ(DRAW_SUCCESS, draw_result);
108 if (!times_to_lose_during_draw_)
109 return draw_result;
111 --times_to_lose_during_draw_;
112 LoseContext();
114 times_to_fail_create_ = times_to_fail_recreate_;
115 times_to_fail_recreate_ = 0;
117 return draw_result;
120 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
121 committed_at_least_once_ = true;
123 if (!times_to_lose_during_commit_)
124 return;
125 --times_to_lose_during_commit_;
126 LoseContext();
128 times_to_fail_create_ = times_to_fail_recreate_;
129 times_to_fail_recreate_ = 0;
132 virtual void DidFailToInitializeOutputSurface() OVERRIDE {
133 ++times_create_failed_;
136 virtual void TearDown() OVERRIDE {
137 LayerTreeTest::TearDown();
138 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
141 void ExpectCreateToFail() { ++times_to_expect_create_failed_; }
143 protected:
144 TestWebGraphicsContext3D* context3d_;
145 int times_to_fail_create_;
146 int times_to_lose_during_commit_;
147 int times_to_lose_during_draw_;
148 int times_to_fail_recreate_;
149 int times_to_expect_create_failed_;
150 int times_create_failed_;
151 bool committed_at_least_once_;
152 bool context_should_support_io_surface_;
153 bool fallback_context_works_;
156 class LayerTreeHostContextTestLostContextSucceeds
157 : public LayerTreeHostContextTest {
158 public:
159 LayerTreeHostContextTestLostContextSucceeds()
160 : LayerTreeHostContextTest(),
161 test_case_(0),
162 num_losses_(0),
163 num_losses_last_test_case_(-1),
164 recovered_context_(true),
165 first_initialized_(false) {}
167 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
169 virtual void DidInitializeOutputSurface() OVERRIDE {
170 if (first_initialized_)
171 ++num_losses_;
172 else
173 first_initialized_ = true;
175 recovered_context_ = true;
178 virtual void AfterTest() OVERRIDE { EXPECT_EQ(7u, test_case_); }
180 virtual void DidCommitAndDrawFrame() OVERRIDE {
181 // If the last frame had a context loss, then we'll commit again to
182 // recover.
183 if (!recovered_context_)
184 return;
185 if (times_to_lose_during_commit_)
186 return;
187 if (times_to_lose_during_draw_)
188 return;
190 recovered_context_ = false;
191 if (NextTestCase())
192 InvalidateAndSetNeedsCommit();
193 else
194 EndTest();
197 virtual void InvalidateAndSetNeedsCommit() {
198 // Cause damage so we try to draw.
199 layer_tree_host()->root_layer()->SetNeedsDisplay();
200 layer_tree_host()->SetNeedsCommit();
203 bool NextTestCase() {
204 static const TestCase kTests[] = {
205 // Losing the context and failing to recreate it (or losing it again
206 // immediately) a small number of times should succeed.
208 1, // times_to_lose_during_commit
209 0, // times_to_lose_during_draw
210 0, // times_to_fail_recreate
211 false, // fallback_context_works
214 0, // times_to_lose_during_commit
215 1, // times_to_lose_during_draw
216 0, // times_to_fail_recreate
217 false, // fallback_context_works
220 1, // times_to_lose_during_commit
221 0, // times_to_lose_during_draw
222 3, // times_to_fail_recreate
223 false, // fallback_context_works
226 0, // times_to_lose_during_commit
227 1, // times_to_lose_during_draw
228 3, // times_to_fail_recreate
229 false, // fallback_context_works
231 // Losing the context and recreating it any number of times should
232 // succeed.
234 10, // times_to_lose_during_commit
235 0, // times_to_lose_during_draw
236 0, // times_to_fail_recreate
237 false, // fallback_context_works
240 0, // times_to_lose_during_commit
241 10, // times_to_lose_during_draw
242 0, // times_to_fail_recreate
243 false, // fallback_context_works
245 // Losing the context, failing to reinitialize it, and making a fallback
246 // context should work.
248 0, // times_to_lose_during_commit
249 1, // times_to_lose_during_draw
250 0, // times_to_fail_recreate
251 true, // fallback_context_works
255 if (test_case_ >= arraysize(kTests))
256 return false;
257 // Make sure that we lost our context at least once in the last test run so
258 // the test did something.
259 EXPECT_GT(num_losses_, num_losses_last_test_case_);
260 num_losses_last_test_case_ = num_losses_;
262 times_to_lose_during_commit_ =
263 kTests[test_case_].times_to_lose_during_commit;
264 times_to_lose_during_draw_ = kTests[test_case_].times_to_lose_during_draw;
265 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
266 fallback_context_works_ = kTests[test_case_].fallback_context_works;
267 ++test_case_;
268 return true;
271 struct TestCase {
272 int times_to_lose_during_commit;
273 int times_to_lose_during_draw;
274 int times_to_fail_recreate;
275 bool fallback_context_works;
278 protected:
279 size_t test_case_;
280 int num_losses_;
281 int num_losses_last_test_case_;
282 bool recovered_context_;
283 bool first_initialized_;
286 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
288 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
289 : public LayerTreeHostContextTest {
290 public:
291 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
292 : LayerTreeHostContextTest() {}
294 virtual void WillBeginTest() OVERRIDE {
295 // Override and do not signal SetLayerTreeHostClientReady.
298 virtual void BeginTest() OVERRIDE {
299 PostSetNeedsCommitToMainThread();
300 EndTest();
303 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
304 OVERRIDE {
305 EXPECT_TRUE(false);
306 return scoped_ptr<OutputSurface>();
309 virtual void DidInitializeOutputSurface() OVERRIDE { EXPECT_TRUE(false); }
311 virtual void AfterTest() OVERRIDE {
315 SINGLE_AND_MULTI_THREAD_TEST_F(
316 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
318 class LayerTreeHostContextTestLostContextSucceedsWithContent
319 : public LayerTreeHostContextTestLostContextSucceeds {
320 public:
321 virtual void SetupTree() OVERRIDE {
322 root_ = Layer::Create();
323 root_->SetBounds(gfx::Size(10, 10));
324 root_->SetIsDrawable(true);
326 content_ = FakeContentLayer::Create(&client_);
327 content_->SetBounds(gfx::Size(10, 10));
328 content_->SetIsDrawable(true);
330 root_->AddChild(content_);
332 layer_tree_host()->SetRootLayer(root_);
333 LayerTreeHostContextTest::SetupTree();
336 virtual void InvalidateAndSetNeedsCommit() OVERRIDE {
337 // Invalidate the render surface so we don't try to use a cached copy of the
338 // surface. We want to make sure to test the drawing paths for drawing to
339 // a child surface.
340 content_->SetNeedsDisplay();
341 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
344 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
345 FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>(
346 host_impl->active_tree()->root_layer()->children()[0]);
347 // Even though the context was lost, we should have a resource. The
348 // TestWebGraphicsContext3D ensures that this resource is created with
349 // the active context.
350 EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
353 protected:
354 FakeContentLayerClient client_;
355 scoped_refptr<Layer> root_;
356 scoped_refptr<ContentLayer> content_;
359 // This test uses TiledLayer to check for a working context.
360 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
361 LayerTreeHostContextTestLostContextSucceedsWithContent);
363 class LayerTreeHostContextTestCreateOutputSurfaceFails
364 : public LayerTreeHostContextTest {
365 public:
366 // Run a test that initially fails OutputSurface creation |times_to_fail|
367 // times. If |expect_fallback_attempt| is |true|, an attempt to create a
368 // fallback/software OutputSurface is expected to occur.
369 LayerTreeHostContextTestCreateOutputSurfaceFails(int times_to_fail,
370 bool expect_fallback_attempt)
371 : times_to_fail_(times_to_fail),
372 expect_fallback_attempt_(expect_fallback_attempt),
373 did_attempt_fallback_(false),
374 times_initialized_(0) {
375 times_to_fail_create_ = times_to_fail_;
378 virtual void BeginTest() OVERRIDE {
379 PostSetNeedsCommitToMainThread();
382 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
383 OVERRIDE {
384 scoped_ptr<FakeOutputSurface> surface =
385 LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
387 if (surface)
388 EXPECT_EQ(times_to_fail_, times_create_failed_);
390 did_attempt_fallback_ = fallback;
391 return surface.Pass();
394 virtual void DidInitializeOutputSurface() OVERRIDE { times_initialized_++; }
396 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
397 EndTest();
400 virtual void AfterTest() OVERRIDE {
401 EXPECT_EQ(times_to_fail_, times_create_failed_);
402 EXPECT_NE(0, times_initialized_);
403 EXPECT_EQ(expect_fallback_attempt_, did_attempt_fallback_);
406 private:
407 int times_to_fail_;
408 bool expect_fallback_attempt_;
409 bool did_attempt_fallback_;
410 int times_initialized_;
413 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
414 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
415 public:
416 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
417 : LayerTreeHostContextTestCreateOutputSurfaceFails(1, false) {}
420 SINGLE_AND_MULTI_THREAD_TEST_F(
421 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce);
423 // After 4 failures we expect an attempt to create a fallback/software
424 // OutputSurface.
425 class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
426 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
427 public:
428 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback()
429 : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true) {}
432 SINGLE_AND_MULTI_THREAD_TEST_F(
433 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback);
435 class LayerTreeHostContextTestLostContextAndEvictTextures
436 : public LayerTreeHostContextTest {
437 public:
438 LayerTreeHostContextTestLostContextAndEvictTextures()
439 : LayerTreeHostContextTest(),
440 layer_(FakeContentLayer::Create(&client_)),
441 impl_host_(0),
442 num_commits_(0) {}
444 virtual void SetupTree() OVERRIDE {
445 layer_->SetBounds(gfx::Size(10, 20));
446 layer_tree_host()->SetRootLayer(layer_);
447 LayerTreeHostContextTest::SetupTree();
450 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
452 void PostEvictTextures() {
453 if (HasImplThread()) {
454 ImplThreadTaskRunner()->PostTask(
455 FROM_HERE,
456 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
457 EvictTexturesOnImplThread,
458 base::Unretained(this)));
459 } else {
460 DebugScopedSetImplThread impl(proxy());
461 EvictTexturesOnImplThread();
465 void EvictTexturesOnImplThread() {
466 impl_host_->EvictTexturesForTesting();
467 if (lose_after_evict_)
468 LoseContext();
471 virtual void DidCommitAndDrawFrame() OVERRIDE {
472 if (num_commits_ > 1)
473 return;
474 EXPECT_TRUE(layer_->HaveBackingAt(0, 0));
475 PostEvictTextures();
478 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
479 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
480 if (num_commits_ > 1)
481 return;
482 ++num_commits_;
483 if (!lose_after_evict_)
484 LoseContext();
485 impl_host_ = impl;
488 virtual void DidInitializeOutputSurface() OVERRIDE { EndTest(); }
490 virtual void AfterTest() OVERRIDE {}
492 protected:
493 bool lose_after_evict_;
494 FakeContentLayerClient client_;
495 scoped_refptr<FakeContentLayer> layer_;
496 LayerTreeHostImpl* impl_host_;
497 int num_commits_;
500 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
501 LoseAfterEvict_SingleThread_DirectRenderer) {
502 lose_after_evict_ = true;
503 RunTest(false, false, false);
506 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
507 LoseAfterEvict_SingleThread_DelegatingRenderer) {
508 lose_after_evict_ = true;
509 RunTest(false, true, false);
512 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
513 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) {
514 lose_after_evict_ = true;
515 RunTest(true, false, false);
518 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
519 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
520 lose_after_evict_ = true;
521 RunTest(true, true, false);
524 // Flaky on all platforms, http://crbug.com/310979
525 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
526 DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
527 lose_after_evict_ = true;
528 RunTest(true, true, true);
531 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
532 LoseBeforeEvict_SingleThread_DirectRenderer) {
533 lose_after_evict_ = false;
534 RunTest(false, false, false);
537 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
538 LoseBeforeEvict_SingleThread_DelegatingRenderer) {
539 lose_after_evict_ = false;
540 RunTest(false, true, false);
543 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
544 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) {
545 lose_after_evict_ = false;
546 RunTest(true, false, false);
549 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
550 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) {
551 lose_after_evict_ = false;
552 RunTest(true, false, true);
555 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
556 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
557 lose_after_evict_ = false;
558 RunTest(true, true, false);
561 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
562 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
563 lose_after_evict_ = false;
564 RunTest(true, true, true);
567 class LayerTreeHostContextTestLostContextWhileUpdatingResources
568 : public LayerTreeHostContextTest {
569 public:
570 LayerTreeHostContextTestLostContextWhileUpdatingResources()
571 : parent_(FakeContentLayer::Create(&client_)),
572 num_children_(50),
573 times_to_lose_on_end_query_(3) {}
575 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() OVERRIDE {
576 scoped_ptr<TestWebGraphicsContext3D> context =
577 LayerTreeHostContextTest::CreateContext3d();
578 if (times_to_lose_on_end_query_) {
579 --times_to_lose_on_end_query_;
580 context->set_times_end_query_succeeds(5);
582 return context.Pass();
585 virtual void SetupTree() OVERRIDE {
586 parent_->SetBounds(gfx::Size(num_children_, 1));
588 for (int i = 0; i < num_children_; i++) {
589 scoped_refptr<FakeContentLayer> child =
590 FakeContentLayer::Create(&client_);
591 child->SetPosition(gfx::PointF(i, 0.f));
592 child->SetBounds(gfx::Size(1, 1));
593 parent_->AddChild(child);
596 layer_tree_host()->SetRootLayer(parent_);
597 LayerTreeHostContextTest::SetupTree();
600 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
602 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
603 EXPECT_EQ(0, times_to_lose_on_end_query_);
604 EndTest();
607 virtual void AfterTest() OVERRIDE {
608 EXPECT_EQ(0, times_to_lose_on_end_query_);
611 private:
612 FakeContentLayerClient client_;
613 scoped_refptr<FakeContentLayer> parent_;
614 int num_children_;
615 int times_to_lose_on_end_query_;
618 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
619 LayerTreeHostContextTestLostContextWhileUpdatingResources);
621 class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest {
622 public:
623 LayerTreeHostContextTestLayersNotified()
624 : LayerTreeHostContextTest(), num_commits_(0) {}
626 virtual void SetupTree() OVERRIDE {
627 root_ = FakeContentLayer::Create(&client_);
628 child_ = FakeContentLayer::Create(&client_);
629 grandchild_ = FakeContentLayer::Create(&client_);
631 root_->AddChild(child_);
632 child_->AddChild(grandchild_);
634 layer_tree_host()->SetRootLayer(root_);
635 LayerTreeHostContextTest::SetupTree();
638 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
640 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
641 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
643 FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>(
644 host_impl->active_tree()->root_layer());
645 FakeContentLayerImpl* child =
646 static_cast<FakeContentLayerImpl*>(root->children()[0]);
647 FakeContentLayerImpl* grandchild =
648 static_cast<FakeContentLayerImpl*>(child->children()[0]);
650 ++num_commits_;
651 switch (num_commits_) {
652 case 1:
653 EXPECT_EQ(0u, root->lost_output_surface_count());
654 EXPECT_EQ(0u, child->lost_output_surface_count());
655 EXPECT_EQ(0u, grandchild->lost_output_surface_count());
656 // Lose the context and struggle to recreate it.
657 LoseContext();
658 times_to_fail_create_ = 1;
659 break;
660 case 2:
661 EXPECT_GE(1u, root->lost_output_surface_count());
662 EXPECT_GE(1u, child->lost_output_surface_count());
663 EXPECT_GE(1u, grandchild->lost_output_surface_count());
664 EndTest();
665 break;
666 default:
667 NOTREACHED();
671 virtual void AfterTest() OVERRIDE {}
673 private:
674 int num_commits_;
676 FakeContentLayerClient client_;
677 scoped_refptr<FakeContentLayer> root_;
678 scoped_refptr<FakeContentLayer> child_;
679 scoped_refptr<FakeContentLayer> grandchild_;
682 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
684 class LayerTreeHostContextTestDontUseLostResources
685 : public LayerTreeHostContextTest {
686 public:
687 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
688 context_should_support_io_surface_ = true;
690 child_output_surface_ = FakeOutputSurface::Create3d();
691 child_output_surface_->BindToClient(&output_surface_client_);
692 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
693 child_resource_provider_ =
694 ResourceProvider::Create(child_output_surface_.get(),
695 shared_bitmap_manager_.get(),
696 NULL,
698 false,
700 false);
703 static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
705 virtual void SetupTree() OVERRIDE {
706 gpu::gles2::GLES2Interface* gl =
707 child_output_surface_->context_provider()->ContextGL();
709 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
711 scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
712 pass_for_quad->SetNew(
713 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
714 RenderPassId(2, 1),
715 gfx::Rect(0, 0, 10, 10),
716 gfx::Rect(0, 0, 10, 10),
717 gfx::Transform());
719 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
720 pass->SetNew(RenderPassId(1, 1),
721 gfx::Rect(0, 0, 10, 10),
722 gfx::Rect(0, 0, 10, 10),
723 gfx::Transform());
724 pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
725 RenderPassId(2, 1));
727 frame_data->render_pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
728 frame_data->render_pass_list.push_back(pass.PassAs<RenderPass>());
730 delegated_resource_collection_ = new DelegatedFrameResourceCollection;
731 delegated_frame_provider_ = new DelegatedFrameProvider(
732 delegated_resource_collection_.get(), frame_data.Pass());
734 ResourceProvider::ResourceId resource =
735 child_resource_provider_->CreateResource(
736 gfx::Size(4, 4),
737 GL_CLAMP_TO_EDGE,
738 ResourceProvider::TextureHintImmutable,
739 RGBA_8888);
740 ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
741 resource);
743 gpu::Mailbox mailbox;
744 gl->GenMailboxCHROMIUM(mailbox.name);
745 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
747 scoped_refptr<Layer> root = Layer::Create();
748 root->SetBounds(gfx::Size(10, 10));
749 root->SetIsDrawable(true);
751 scoped_refptr<FakeDelegatedRendererLayer> delegated =
752 FakeDelegatedRendererLayer::Create(delegated_frame_provider_.get());
753 delegated->SetBounds(gfx::Size(10, 10));
754 delegated->SetIsDrawable(true);
755 root->AddChild(delegated);
757 scoped_refptr<ContentLayer> content = ContentLayer::Create(&client_);
758 content->SetBounds(gfx::Size(10, 10));
759 content->SetIsDrawable(true);
760 root->AddChild(content);
762 scoped_refptr<TextureLayer> texture = TextureLayer::CreateForMailbox(NULL);
763 texture->SetBounds(gfx::Size(10, 10));
764 texture->SetIsDrawable(true);
765 texture->SetTextureMailbox(
766 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
767 SingleReleaseCallback::Create(
768 base::Bind(&LayerTreeHostContextTestDontUseLostResources::
769 EmptyReleaseCallback)));
770 root->AddChild(texture);
772 scoped_refptr<ContentLayer> mask = ContentLayer::Create(&client_);
773 mask->SetBounds(gfx::Size(10, 10));
775 scoped_refptr<ContentLayer> content_with_mask =
776 ContentLayer::Create(&client_);
777 content_with_mask->SetBounds(gfx::Size(10, 10));
778 content_with_mask->SetIsDrawable(true);
779 content_with_mask->SetMaskLayer(mask.get());
780 root->AddChild(content_with_mask);
782 scoped_refptr<VideoLayer> video_color =
783 VideoLayer::Create(&color_frame_provider_, media::VIDEO_ROTATION_0);
784 video_color->SetBounds(gfx::Size(10, 10));
785 video_color->SetIsDrawable(true);
786 root->AddChild(video_color);
788 scoped_refptr<VideoLayer> video_hw =
789 VideoLayer::Create(&hw_frame_provider_, media::VIDEO_ROTATION_0);
790 video_hw->SetBounds(gfx::Size(10, 10));
791 video_hw->SetIsDrawable(true);
792 root->AddChild(video_hw);
794 scoped_refptr<VideoLayer> video_scaled_hw =
795 VideoLayer::Create(&scaled_hw_frame_provider_, media::VIDEO_ROTATION_0);
796 video_scaled_hw->SetBounds(gfx::Size(10, 10));
797 video_scaled_hw->SetIsDrawable(true);
798 root->AddChild(video_scaled_hw);
800 color_video_frame_ = VideoFrame::CreateColorFrame(
801 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
802 hw_video_frame_ =
803 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
804 mailbox, GL_TEXTURE_2D, sync_point)),
805 media::VideoFrame::ReleaseMailboxCB(),
806 gfx::Size(4, 4),
807 gfx::Rect(0, 0, 4, 4),
808 gfx::Size(4, 4),
809 base::TimeDelta(),
810 VideoFrame::ReadPixelsCB());
811 scaled_hw_video_frame_ =
812 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
813 mailbox, GL_TEXTURE_2D, sync_point)),
814 media::VideoFrame::ReleaseMailboxCB(),
815 gfx::Size(4, 4),
816 gfx::Rect(0, 0, 3, 2),
817 gfx::Size(4, 4),
818 base::TimeDelta(),
819 VideoFrame::ReadPixelsCB());
821 color_frame_provider_.set_frame(color_video_frame_);
822 hw_frame_provider_.set_frame(hw_video_frame_);
823 scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
825 if (!delegating_renderer()) {
826 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
827 scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
828 io_surface->SetBounds(gfx::Size(10, 10));
829 io_surface->SetIsDrawable(true);
830 io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10));
831 root->AddChild(io_surface);
834 // Enable the hud.
835 LayerTreeDebugState debug_state;
836 debug_state.show_property_changed_rects = true;
837 layer_tree_host()->SetDebugState(debug_state);
839 scoped_refptr<PaintedScrollbarLayer> scrollbar =
840 PaintedScrollbarLayer::Create(
841 scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), content->id());
842 scrollbar->SetBounds(gfx::Size(10, 10));
843 scrollbar->SetIsDrawable(true);
844 root->AddChild(scrollbar);
846 layer_tree_host()->SetRootLayer(root);
847 LayerTreeHostContextTest::SetupTree();
850 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
852 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
853 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
855 if (host_impl->active_tree()->source_frame_number() == 3) {
856 // On the third commit we're recovering from context loss. Hardware
857 // video frames should not be reused by the VideoFrameProvider, but
858 // software frames can be.
859 hw_frame_provider_.set_frame(NULL);
860 scaled_hw_frame_provider_.set_frame(NULL);
864 virtual DrawResult PrepareToDrawOnThread(
865 LayerTreeHostImpl* host_impl,
866 LayerTreeHostImpl::FrameData* frame,
867 DrawResult draw_result) OVERRIDE {
868 if (host_impl->active_tree()->source_frame_number() == 2) {
869 // Lose the context during draw on the second commit. This will cause
870 // a third commit to recover.
871 context3d_->set_times_bind_texture_succeeds(0);
873 return draw_result;
876 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
877 OVERRIDE {
878 // This will get called twice:
879 // First when we create the initial output surface...
880 if (layer_tree_host()->source_frame_number() > 0) {
881 // ... and then again after we forced the context to be lost.
882 lost_context_ = true;
884 return LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
887 virtual void DidCommitAndDrawFrame() OVERRIDE {
888 ASSERT_TRUE(layer_tree_host()->hud_layer());
889 // End the test once we know the 3nd frame drew.
890 if (layer_tree_host()->source_frame_number() < 5) {
891 layer_tree_host()->root_layer()->SetNeedsDisplay();
892 layer_tree_host()->SetNeedsCommit();
893 } else {
894 EndTest();
898 virtual void AfterTest() OVERRIDE { EXPECT_TRUE(lost_context_); }
900 private:
901 FakeContentLayerClient client_;
902 bool lost_context_;
904 FakeOutputSurfaceClient output_surface_client_;
905 scoped_ptr<FakeOutputSurface> child_output_surface_;
906 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
907 scoped_ptr<ResourceProvider> child_resource_provider_;
909 scoped_refptr<DelegatedFrameResourceCollection>
910 delegated_resource_collection_;
911 scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
913 scoped_refptr<VideoFrame> color_video_frame_;
914 scoped_refptr<VideoFrame> hw_video_frame_;
915 scoped_refptr<VideoFrame> scaled_hw_video_frame_;
917 FakeVideoFrameProvider color_frame_provider_;
918 FakeVideoFrameProvider hw_frame_provider_;
919 FakeVideoFrameProvider scaled_hw_frame_provider_;
922 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
924 class ImplSidePaintingLayerTreeHostContextTest
925 : public LayerTreeHostContextTest {
926 public:
927 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
928 settings->impl_side_painting = true;
932 class LayerTreeHostContextTestImplSidePainting
933 : public ImplSidePaintingLayerTreeHostContextTest {
934 public:
935 virtual void SetupTree() OVERRIDE {
936 scoped_refptr<Layer> root = Layer::Create();
937 root->SetBounds(gfx::Size(10, 10));
938 root->SetIsDrawable(true);
940 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
941 picture->SetBounds(gfx::Size(10, 10));
942 picture->SetIsDrawable(true);
943 root->AddChild(picture);
945 layer_tree_host()->SetRootLayer(root);
946 LayerTreeHostContextTest::SetupTree();
949 virtual void BeginTest() OVERRIDE {
950 times_to_lose_during_commit_ = 1;
951 PostSetNeedsCommitToMainThread();
954 virtual void AfterTest() OVERRIDE {}
956 virtual void DidInitializeOutputSurface() OVERRIDE { EndTest(); }
958 private:
959 FakeContentLayerClient client_;
962 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
964 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
965 public:
966 ScrollbarLayerLostContext() : commits_(0) {}
968 virtual void BeginTest() OVERRIDE {
969 scoped_refptr<Layer> scroll_layer = Layer::Create();
970 scrollbar_layer_ =
971 FakePaintedScrollbarLayer::Create(false, true, scroll_layer->id());
972 scrollbar_layer_->SetBounds(gfx::Size(10, 100));
973 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
974 layer_tree_host()->root_layer()->AddChild(scroll_layer);
975 PostSetNeedsCommitToMainThread();
978 virtual void AfterTest() OVERRIDE {}
980 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
981 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
983 ++commits_;
984 switch (commits_) {
985 case 1:
986 // First (regular) update, we should upload 2 resources (thumb, and
987 // backtrack).
988 EXPECT_EQ(1, scrollbar_layer_->update_count());
989 LoseContext();
990 break;
991 case 2:
992 // Second update, after the lost context, we should still upload 2
993 // resources even if the contents haven't changed.
994 EXPECT_EQ(2, scrollbar_layer_->update_count());
995 EndTest();
996 break;
997 default:
998 NOTREACHED();
1002 private:
1003 int commits_;
1004 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
1007 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1009 class UIResourceLostTest : public LayerTreeHostContextTest {
1010 public:
1011 UIResourceLostTest() : time_step_(0) {}
1012 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1013 settings->texture_id_allocation_chunk_size = 1;
1015 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1016 virtual void AfterTest() OVERRIDE {}
1018 // This is called on the main thread after each commit and
1019 // DidActivateTreeOnThread, with the value of time_step_ at the time
1020 // of the call to DidActivateTreeOnThread. Similar tests will do
1021 // work on the main thread in DidCommit but that is unsuitable because
1022 // the main thread work for these tests must happen after
1023 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1024 // painting.
1025 virtual void StepCompleteOnMainThread(int time_step) = 0;
1027 // Called after DidActivateTreeOnThread. If this is done during the commit,
1028 // the call to StepCompleteOnMainThread will not occur until after
1029 // the commit completes, because the main thread is blocked.
1030 void PostStepCompleteToMainThread() {
1031 proxy()->MainThreadTaskRunner()->PostTask(
1032 FROM_HERE,
1033 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal,
1034 base::Unretained(this),
1035 time_step_));
1038 void PostLoseContextToImplThread() {
1039 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1040 ImplThreadTaskRunner()->PostTask(
1041 FROM_HERE,
1042 base::Bind(&LayerTreeHostContextTest::LoseContext,
1043 base::Unretained(this)));
1046 protected:
1047 int time_step_;
1048 scoped_ptr<FakeScopedUIResource> ui_resource_;
1050 private:
1051 void StepCompleteOnMainThreadInternal(int step) {
1052 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1053 StepCompleteOnMainThread(step);
1057 class UIResourceLostTestSimple : public UIResourceLostTest {
1058 public:
1059 // This is called when the commit is complete and the new layer tree has been
1060 // activated.
1061 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1063 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1064 if (!layer_tree_host()->settings().impl_side_painting) {
1065 StepCompleteOnImplThread(impl);
1066 PostStepCompleteToMainThread();
1067 ++time_step_;
1071 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1072 if (layer_tree_host()->settings().impl_side_painting) {
1073 StepCompleteOnImplThread(impl);
1074 PostStepCompleteToMainThread();
1075 ++time_step_;
1080 // Losing context after an UI resource has been created.
1081 class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
1082 public:
1083 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1084 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1085 switch (step) {
1086 case 0:
1087 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1088 // Expects a valid UIResourceId.
1089 EXPECT_NE(0, ui_resource_->id());
1090 PostSetNeedsCommitToMainThread();
1091 break;
1092 case 4:
1093 // Release resource before ending the test.
1094 ui_resource_.reset();
1095 EndTest();
1096 break;
1097 case 5:
1098 NOTREACHED();
1099 break;
1103 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1104 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1105 switch (time_step_) {
1106 case 1:
1107 // The resource should have been created on LTHI after the commit.
1108 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1109 PostSetNeedsCommitToMainThread();
1110 break;
1111 case 2:
1112 LoseContext();
1113 break;
1114 case 3:
1115 // The resources should have been recreated. The bitmap callback should
1116 // have been called once with the resource_lost flag set to true.
1117 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1118 // Resource Id on the impl-side have been recreated as well. Note
1119 // that the same UIResourceId persists after the context lost.
1120 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1121 PostSetNeedsCommitToMainThread();
1122 break;
1127 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
1129 // Losing context before UI resource requests can be commited. Three sequences
1130 // of creation/deletion are considered:
1131 // 1. Create one resource -> Context Lost => Expect the resource to have been
1132 // created.
1133 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1134 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1135 // test_id1_ to have been created.
1136 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1137 // the resource to not exist in the manager.
1138 class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
1139 public:
1140 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1142 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1143 switch (step) {
1144 case 0:
1145 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1146 // Lose the context on the impl thread before the commit.
1147 PostLoseContextToImplThread();
1148 break;
1149 case 2:
1150 // Sequence 2:
1151 // Currently one resource has been created.
1152 test_id0_ = ui_resource_->id();
1153 // Delete this resource.
1154 ui_resource_.reset();
1155 // Create another resource.
1156 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1157 test_id1_ = ui_resource_->id();
1158 // Sanity check that two resource creations return different ids.
1159 EXPECT_NE(test_id0_, test_id1_);
1160 // Lose the context on the impl thread before the commit.
1161 PostLoseContextToImplThread();
1162 break;
1163 case 3:
1164 // Clear the manager of resources.
1165 ui_resource_.reset();
1166 PostSetNeedsCommitToMainThread();
1167 break;
1168 case 4:
1169 // Sequence 3:
1170 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1171 test_id0_ = ui_resource_->id();
1172 // Sanity check the UIResourceId should not be 0.
1173 EXPECT_NE(0, test_id0_);
1174 // Usually ScopedUIResource are deleted from the manager in their
1175 // destructor (so usually ui_resource_.reset()). But here we need
1176 // ui_resource_ for the next step, so call DeleteUIResource directly.
1177 layer_tree_host()->DeleteUIResource(test_id0_);
1178 // Delete the resouce and then lose the context.
1179 PostLoseContextToImplThread();
1180 break;
1181 case 5:
1182 // Release resource before ending the test.
1183 ui_resource_.reset();
1184 EndTest();
1185 break;
1186 case 6:
1187 NOTREACHED();
1188 break;
1192 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1193 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1194 switch (time_step_) {
1195 case 1:
1196 // Sequence 1 (continued):
1197 // The first context lost happens before the resources were created,
1198 // and because it resulted in no resources being destroyed, it does not
1199 // trigger resource re-creation.
1200 EXPECT_EQ(1, ui_resource_->resource_create_count);
1201 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1202 // Resource Id on the impl-side has been created.
1203 PostSetNeedsCommitToMainThread();
1204 break;
1205 case 3:
1206 // Sequence 2 (continued):
1207 // The previous resource should have been deleted.
1208 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1209 // The second resource should have been created.
1210 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
1211 // The second resource called the resource callback once and since the
1212 // context is lost, a "resource lost" callback was also issued.
1213 EXPECT_EQ(2, ui_resource_->resource_create_count);
1214 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1215 break;
1216 case 5:
1217 // Sequence 3 (continued):
1218 // Expect the resource callback to have been called once.
1219 EXPECT_EQ(1, ui_resource_->resource_create_count);
1220 // No "resource lost" callbacks.
1221 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1222 // The UI resource id should not be valid
1223 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1224 break;
1228 private:
1229 UIResourceId test_id0_;
1230 UIResourceId test_id1_;
1233 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
1235 // Losing UI resource before the pending trees is activated but after the
1236 // commit. Impl-side-painting only.
1237 class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
1238 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1239 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1240 switch (step) {
1241 case 0:
1242 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1243 PostSetNeedsCommitToMainThread();
1244 break;
1245 case 3:
1246 test_id_ = ui_resource_->id();
1247 ui_resource_.reset();
1248 PostSetNeedsCommitToMainThread();
1249 break;
1250 case 5:
1251 // Release resource before ending the test.
1252 ui_resource_.reset();
1253 EndTest();
1254 break;
1255 case 6:
1256 // Make sure no extra commits happened.
1257 NOTREACHED();
1261 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1262 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1263 switch (time_step_) {
1264 case 2:
1265 PostSetNeedsCommitToMainThread();
1266 break;
1267 case 4:
1268 PostSetNeedsCommitToMainThread();
1269 break;
1273 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1274 switch (time_step_) {
1275 case 1:
1276 // The resource creation callback has been called.
1277 EXPECT_EQ(1, ui_resource_->resource_create_count);
1278 // The resource is not yet lost (sanity check).
1279 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1280 // The resource should not have been created yet on the impl-side.
1281 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1282 LoseContext();
1283 break;
1284 case 3:
1285 LoseContext();
1286 break;
1290 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1291 LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1292 switch (time_step_) {
1293 case 1:
1294 // The pending requests on the impl-side should have been processed.
1295 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1296 break;
1297 case 2:
1298 // The "lost resource" callback should have been called once.
1299 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1300 break;
1301 case 4:
1302 // The resource is deleted and should not be in the manager. Use
1303 // test_id_ since ui_resource_ has been deleted.
1304 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
1305 break;
1308 PostStepCompleteToMainThread();
1309 ++time_step_;
1312 private:
1313 UIResourceId test_id_;
1316 TEST_F(UIResourceLostBeforeActivateTree,
1317 RunMultiThread_DirectRenderer_ImplSidePaint) {
1318 RunTest(true, false, true);
1321 TEST_F(UIResourceLostBeforeActivateTree,
1322 RunMultiThread_DelegatingRenderer_ImplSidePaint) {
1323 RunTest(true, true, true);
1326 // Resources evicted explicitly and by visibility changes.
1327 class UIResourceLostEviction : public UIResourceLostTestSimple {
1328 public:
1329 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1330 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1331 switch (step) {
1332 case 0:
1333 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1334 EXPECT_NE(0, ui_resource_->id());
1335 PostSetNeedsCommitToMainThread();
1336 break;
1337 case 2:
1338 // Make the tree not visible.
1339 PostSetVisibleToMainThread(false);
1340 break;
1341 case 3:
1342 // Release resource before ending the test.
1343 ui_resource_.reset();
1344 EndTest();
1345 break;
1346 case 4:
1347 NOTREACHED();
1351 virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl,
1352 bool visible) OVERRIDE {
1353 TestWebGraphicsContext3D* context = TestContext();
1354 if (!visible) {
1355 // All resources should have been evicted.
1356 ASSERT_EQ(0u, context->NumTextures());
1357 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1358 EXPECT_EQ(2, ui_resource_->resource_create_count);
1359 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1360 // Drawing is disabled both because of the evicted resources and
1361 // because the renderer is not visible.
1362 EXPECT_FALSE(impl->CanDraw());
1363 // Make the renderer visible again.
1364 PostSetVisibleToMainThread(true);
1368 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1369 TestWebGraphicsContext3D* context = TestContext();
1370 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1371 switch (time_step_) {
1372 case 1:
1373 // The resource should have been created on LTHI after the commit.
1374 ASSERT_EQ(1u, context->NumTextures());
1375 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1376 EXPECT_EQ(1, ui_resource_->resource_create_count);
1377 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1378 EXPECT_TRUE(impl->CanDraw());
1379 // Evict all UI resources. This will trigger a commit.
1380 impl->EvictAllUIResources();
1381 ASSERT_EQ(0u, context->NumTextures());
1382 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1383 EXPECT_EQ(1, ui_resource_->resource_create_count);
1384 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1385 EXPECT_FALSE(impl->CanDraw());
1386 break;
1387 case 2:
1388 // The resource should have been recreated.
1389 ASSERT_EQ(1u, context->NumTextures());
1390 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1391 EXPECT_EQ(2, ui_resource_->resource_create_count);
1392 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1393 EXPECT_TRUE(impl->CanDraw());
1394 break;
1395 case 3:
1396 // The resource should have been recreated after visibility was
1397 // restored.
1398 ASSERT_EQ(1u, context->NumTextures());
1399 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1400 EXPECT_EQ(3, ui_resource_->resource_create_count);
1401 EXPECT_EQ(2, ui_resource_->lost_resource_count);
1402 EXPECT_TRUE(impl->CanDraw());
1403 break;
1408 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1410 class LayerTreeHostContextTestSurfaceCreateCallback
1411 : public LayerTreeHostContextTest {
1412 public:
1413 LayerTreeHostContextTestSurfaceCreateCallback()
1414 : LayerTreeHostContextTest(),
1415 layer_(FakeContentLayer::Create(&client_)) {}
1417 virtual void SetupTree() OVERRIDE {
1418 layer_->SetBounds(gfx::Size(10, 20));
1419 layer_tree_host()->SetRootLayer(layer_);
1420 LayerTreeHostContextTest::SetupTree();
1423 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1425 virtual void DidCommit() OVERRIDE {
1426 switch (layer_tree_host()->source_frame_number()) {
1427 case 1:
1428 EXPECT_EQ(1u, layer_->output_surface_created_count());
1429 layer_tree_host()->SetNeedsCommit();
1430 break;
1431 case 2:
1432 EXPECT_EQ(1u, layer_->output_surface_created_count());
1433 layer_tree_host()->SetNeedsCommit();
1434 break;
1435 case 3:
1436 EXPECT_EQ(1u, layer_->output_surface_created_count());
1437 break;
1438 case 4:
1439 EXPECT_EQ(2u, layer_->output_surface_created_count());
1440 layer_tree_host()->SetNeedsCommit();
1441 break;
1445 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1446 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1447 switch (LastCommittedSourceFrameNumber(impl)) {
1448 case 0:
1449 break;
1450 case 1:
1451 break;
1452 case 2:
1453 LoseContext();
1454 break;
1455 case 3:
1456 EndTest();
1457 break;
1461 virtual void AfterTest() OVERRIDE {}
1463 protected:
1464 FakeContentLayerClient client_;
1465 scoped_refptr<FakeContentLayer> layer_;
1468 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
1470 class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
1471 : public LayerTreeHostContextTest {
1472 protected:
1473 virtual void BeginTest() OVERRIDE {
1474 deferred_ = false;
1475 PostSetNeedsCommitToMainThread();
1478 virtual void ScheduledActionWillSendBeginMainFrame() OVERRIDE {
1479 if (deferred_)
1480 return;
1481 deferred_ = true;
1483 // Defer commits before the BeginFrame arrives, causing it to be delayed.
1484 MainThreadTaskRunner()->PostTask(
1485 FROM_HERE,
1486 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1487 DeferCommitsOnMainThread,
1488 base::Unretained(this),
1489 true));
1490 // Meanwhile, lose the context while we are in defer commits.
1491 ImplThreadTaskRunner()->PostTask(
1492 FROM_HERE,
1493 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1494 LoseContextOnImplThread,
1495 base::Unretained(this)));
1498 void LoseContextOnImplThread() {
1499 LoseContext();
1501 // After losing the context, stop deferring commits.
1502 MainThreadTaskRunner()->PostTask(
1503 FROM_HERE,
1504 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1505 DeferCommitsOnMainThread,
1506 base::Unretained(this),
1507 false));
1510 void DeferCommitsOnMainThread(bool defer_commits) {
1511 layer_tree_host()->SetDeferCommits(defer_commits);
1514 virtual void WillBeginMainFrame() OVERRIDE {
1515 // Don't begin a frame with a lost surface.
1516 EXPECT_FALSE(layer_tree_host()->output_surface_lost());
1519 virtual void DidCommitAndDrawFrame() OVERRIDE { EndTest(); }
1521 virtual void AfterTest() OVERRIDE {}
1523 bool deferred_;
1526 SINGLE_AND_MULTI_THREAD_TEST_F(
1527 LayerTreeHostContextTestLoseAfterSendingBeginMainFrame);
1529 } // namespace
1530 } // namespace cc