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/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"
44 using media::VideoFrame;
49 // These tests deal with losing the 3d graphics context.
50 class LayerTreeHostContextTest : public LayerTreeTest {
52 LayerTreeHostContextTest()
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();
68 context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
69 GL_INNOCENT_CONTEXT_RESET_ARB);
73 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
74 return TestWebGraphicsContext3D::Create();
77 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
79 if (times_to_fail_create_) {
80 --times_to_fail_create_;
82 return scoped_ptr<FakeOutputSurface>();
85 scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
86 context3d_ = context3d.get();
88 if (context_should_support_io_surface_) {
89 context3d_->set_have_extension_io_surface(true);
90 context3d_->set_have_extension_egl_image(true);
93 if (delegating_renderer())
94 return FakeOutputSurface::CreateDelegating3d(context3d.Pass());
96 return FakeOutputSurface::Create3d(context3d.Pass());
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_)
107 --times_to_lose_during_draw_;
110 times_to_fail_create_ = times_to_fail_recreate_;
111 times_to_fail_recreate_ = 0;
116 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
117 committed_at_least_once_ = true;
119 if (!times_to_lose_during_commit_)
121 --times_to_lose_during_commit_;
124 times_to_fail_create_ = times_to_fail_recreate_;
125 times_to_fail_recreate_ = 0;
128 virtual void DidFailToInitializeOutputSurface() OVERRIDE {
129 ++times_create_failed_;
132 virtual void TearDown() OVERRIDE {
133 LayerTreeTest::TearDown();
134 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
137 void ExpectCreateToFail() { ++times_to_expect_create_failed_; }
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_;
152 class LayerTreeHostContextTestLostContextSucceeds
153 : public LayerTreeHostContextTest {
155 LayerTreeHostContextTestLostContextSucceeds()
156 : LayerTreeHostContextTest(),
159 num_losses_last_test_case_(-1),
160 recovered_context_(true),
161 first_initialized_(false) {}
163 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
165 virtual void DidInitializeOutputSurface() OVERRIDE {
166 if (first_initialized_)
169 first_initialized_ = true;
171 recovered_context_ = true;
174 virtual void AfterTest() OVERRIDE { EXPECT_EQ(7u, test_case_); }
176 virtual void DidCommitAndDrawFrame() OVERRIDE {
177 // If the last frame had a context loss, then we'll commit again to
179 if (!recovered_context_)
181 if (times_to_lose_during_commit_)
183 if (times_to_lose_during_draw_)
186 recovered_context_ = false;
188 InvalidateAndSetNeedsCommit();
193 virtual void InvalidateAndSetNeedsCommit() {
194 // Cause damage so we try to draw.
195 layer_tree_host()->root_layer()->SetNeedsDisplay();
196 layer_tree_host()->SetNeedsCommit();
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
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
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
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
223 // Losing the context and recreating it any number of times should
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
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
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
243 if (test_case_ >= arraysize(kTests))
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_;
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;
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;
269 int num_losses_last_test_case_;
270 bool recovered_context_;
271 bool first_initialized_;
274 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
276 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
277 : public LayerTreeHostContextTest {
279 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
280 : LayerTreeHostContextTest() {}
282 virtual void WillBeginTest() OVERRIDE {
283 // Override and do not signal SetLayerTreeHostClientReady.
286 virtual void BeginTest() OVERRIDE {
287 PostSetNeedsCommitToMainThread();
291 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
294 return scoped_ptr<OutputSurface>();
297 virtual void DidInitializeOutputSurface() OVERRIDE { EXPECT_TRUE(false); }
299 virtual void AfterTest() OVERRIDE {
303 MULTI_THREAD_TEST_F(LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
305 class LayerTreeHostContextTestLostContextSucceedsWithContent
306 : public LayerTreeHostContextTestLostContextSucceeds {
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);
314 content_ = FakeContentLayer::Create(&client_);
315 content_->SetBounds(gfx::Size(10, 10));
316 content_->SetAnchorPoint(gfx::PointF());
317 content_->SetIsDrawable(true);
319 root_->AddChild(content_);
321 layer_tree_host()->SetRootLayer(root_);
322 LayerTreeHostContextTest::SetupTree();
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
329 content_->SetNeedsDisplay();
330 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
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));
343 FakeContentLayerClient client_;
344 scoped_refptr<Layer> root_;
345 scoped_refptr<ContentLayer> content_;
348 // This test uses TiledLayer to check for a working context.
349 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
350 LayerTreeHostContextTestLostContextSucceedsWithContent);
352 class LayerTreeHostContextTestCreateOutputSurfaceFails
353 : public LayerTreeHostContextTest {
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) {}
365 virtual void BeginTest() OVERRIDE {
366 times_to_fail_create_ = times_to_fail_;
367 PostSetNeedsCommitToMainThread();
370 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
372 scoped_ptr<FakeOutputSurface> surface =
373 LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
376 EXPECT_EQ(times_to_fail_, times_create_failed_);
378 did_attempt_fallback_ = fallback;
379 return surface.Pass();
382 virtual void DidInitializeOutputSurface() OVERRIDE { times_initialized_++; }
384 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
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_);
396 bool expect_fallback_attempt_;
397 bool did_attempt_fallback_;
398 int times_initialized_;
401 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
402 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
404 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
405 : LayerTreeHostContextTestCreateOutputSurfaceFails(1, false) {}
408 SINGLE_AND_MULTI_THREAD_TEST_F(
409 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce);
411 // After 4 failures we expect an attempt to create a fallback/software
413 class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
414 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
416 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback()
417 : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true) {}
420 SINGLE_AND_MULTI_THREAD_TEST_F(
421 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback);
423 class LayerTreeHostContextTestLostContextAndEvictTextures
424 : public LayerTreeHostContextTest {
426 LayerTreeHostContextTestLostContextAndEvictTextures()
427 : LayerTreeHostContextTest(),
428 layer_(FakeContentLayer::Create(&client_)),
432 virtual void SetupTree() OVERRIDE {
433 layer_->SetBounds(gfx::Size(10, 20));
434 layer_tree_host()->SetRootLayer(layer_);
435 LayerTreeHostContextTest::SetupTree();
438 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
440 void PostEvictTextures() {
441 if (HasImplThread()) {
442 ImplThreadTaskRunner()->PostTask(
444 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
445 EvictTexturesOnImplThread,
446 base::Unretained(this)));
448 DebugScopedSetImplThread impl(proxy());
449 EvictTexturesOnImplThread();
453 void EvictTexturesOnImplThread() {
454 impl_host_->EvictTexturesForTesting();
455 if (lose_after_evict_)
459 virtual void DidCommitAndDrawFrame() OVERRIDE {
460 if (num_commits_ > 1)
462 EXPECT_TRUE(layer_->HaveBackingAt(0, 0));
466 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
467 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
468 if (num_commits_ > 1)
471 if (!lose_after_evict_)
476 virtual void DidInitializeOutputSurface() OVERRIDE { EndTest(); }
478 virtual void AfterTest() OVERRIDE {}
481 bool lose_after_evict_;
482 FakeContentLayerClient client_;
483 scoped_refptr<FakeContentLayer> layer_;
484 LayerTreeHostImpl* impl_host_;
488 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
489 LoseAfterEvict_SingleThread_DirectRenderer) {
490 lose_after_evict_ = true;
491 RunTest(false, false, false);
494 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
495 LoseAfterEvict_SingleThread_DelegatingRenderer) {
496 lose_after_evict_ = true;
497 RunTest(false, true, false);
500 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
501 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) {
502 lose_after_evict_ = true;
503 RunTest(true, false, false);
506 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
507 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
508 lose_after_evict_ = true;
509 RunTest(true, true, false);
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);
519 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
520 LoseBeforeEvict_SingleThread_DirectRenderer) {
521 lose_after_evict_ = false;
522 RunTest(false, false, false);
525 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
526 LoseBeforeEvict_SingleThread_DelegatingRenderer) {
527 lose_after_evict_ = false;
528 RunTest(false, true, false);
531 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
532 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) {
533 lose_after_evict_ = false;
534 RunTest(true, false, false);
537 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
538 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) {
539 lose_after_evict_ = false;
540 RunTest(true, false, true);
543 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
544 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
545 lose_after_evict_ = false;
546 RunTest(true, true, false);
549 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
550 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
551 lose_after_evict_ = false;
552 RunTest(true, true, true);
555 class LayerTreeHostContextTestLostContextWhileUpdatingResources
556 : public LayerTreeHostContextTest {
558 LayerTreeHostContextTestLostContextWhileUpdatingResources()
559 : parent_(FakeContentLayer::Create(&client_)),
561 times_to_lose_on_end_query_(3) {}
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);
570 return context.Pass();
573 virtual void SetupTree() OVERRIDE {
574 parent_->SetBounds(gfx::Size(num_children_, 1));
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);
584 layer_tree_host()->SetRootLayer(parent_);
585 LayerTreeHostContextTest::SetupTree();
588 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
590 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
591 EXPECT_EQ(0, times_to_lose_on_end_query_);
595 virtual void AfterTest() OVERRIDE {
596 EXPECT_EQ(0, times_to_lose_on_end_query_);
600 FakeContentLayerClient client_;
601 scoped_refptr<FakeContentLayer> parent_;
603 int times_to_lose_on_end_query_;
606 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
607 LayerTreeHostContextTestLostContextWhileUpdatingResources);
609 class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest {
611 LayerTreeHostContextTestLayersNotified()
612 : LayerTreeHostContextTest(), num_commits_(0) {}
614 virtual void SetupTree() OVERRIDE {
615 root_ = FakeContentLayer::Create(&client_);
616 child_ = FakeContentLayer::Create(&client_);
617 grandchild_ = FakeContentLayer::Create(&client_);
619 root_->AddChild(child_);
620 child_->AddChild(grandchild_);
622 layer_tree_host()->SetRootLayer(root_);
623 LayerTreeHostContextTest::SetupTree();
626 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
628 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
629 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
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]);
639 switch (num_commits_) {
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.
646 times_to_fail_create_ = 1;
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());
659 virtual void AfterTest() OVERRIDE {}
664 FakeContentLayerClient client_;
665 scoped_refptr<FakeContentLayer> root_;
666 scoped_refptr<FakeContentLayer> child_;
667 scoped_refptr<FakeContentLayer> grandchild_;
670 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
672 class LayerTreeHostContextTestDontUseLostResources
673 : public LayerTreeHostContextTest {
675 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
676 context_should_support_io_surface_ = true;
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,
686 static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
688 virtual void SetupTree() OVERRIDE {
689 gpu::gles2::GLES2Interface* gl =
690 child_output_surface_->context_provider()->ContextGL();
692 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
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),
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),
707 pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
708 RenderPass::Id(2, 1));
710 frame_data->render_pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
711 frame_data->render_pass_list.push_back(pass.PassAs<RenderPass>());
713 delegated_resource_collection_ = new DelegatedFrameResourceCollection;
714 delegated_frame_provider_ = new DelegatedFrameProvider(
715 delegated_resource_collection_.get(), frame_data.Pass());
717 ResourceProvider::ResourceId resource =
718 child_resource_provider_->CreateResource(
721 ResourceProvider::TextureUsageAny,
723 ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
726 gpu::Mailbox mailbox;
727 gl->GenMailboxCHROMIUM(mailbox.name);
728 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
730 scoped_refptr<Layer> root = Layer::Create();
731 root->SetBounds(gfx::Size(10, 10));
732 root->SetAnchorPoint(gfx::PointF());
733 root->SetIsDrawable(true);
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);
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);
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);
759 scoped_refptr<ContentLayer> mask = ContentLayer::Create(&client_);
760 mask->SetBounds(gfx::Size(10, 10));
761 mask->SetAnchorPoint(gfx::PointF());
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);
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);
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);
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);
792 color_video_frame_ = VideoFrame::CreateColorFrame(
793 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
795 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
796 mailbox, GL_TEXTURE_2D, sync_point)),
797 media::VideoFrame::ReleaseMailboxCB(),
799 gfx::Rect(0, 0, 4, 4),
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(),
808 gfx::Rect(0, 0, 3, 2),
811 VideoFrame::ReadPixelsCB());
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_);
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);
828 LayerTreeDebugState debug_state;
829 debug_state.show_property_changed_rects = true;
830 layer_tree_host()->SetDebugState(debug_state);
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);
840 layer_tree_host()->SetRootLayer(root);
841 LayerTreeHostContextTest::SetupTree();
844 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
846 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
847 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
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);
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);
870 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
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;
878 return LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
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();
892 virtual void AfterTest() OVERRIDE { EXPECT_TRUE(lost_context_); }
895 FakeContentLayerClient client_;
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_;
903 scoped_refptr<DelegatedFrameResourceCollection>
904 delegated_resource_collection_;
905 scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
907 scoped_refptr<VideoFrame> color_video_frame_;
908 scoped_refptr<VideoFrame> hw_video_frame_;
909 scoped_refptr<VideoFrame> scaled_hw_video_frame_;
911 FakeVideoFrameProvider color_frame_provider_;
912 FakeVideoFrameProvider hw_frame_provider_;
913 FakeVideoFrameProvider scaled_hw_frame_provider_;
916 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
918 class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
919 : public LayerTreeHostContextTest {
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());
926 times_output_surface_created_ = 0;
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();
935 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(1, 1));
936 EXPECT_EQ(!delegating_renderer(), result);
937 EXPECT_EQ(1, times_output_surface_created_);
940 virtual void DidInitializeOutputSurface() OVERRIDE {
941 ++times_output_surface_created_;
944 virtual void DidCommitAndDrawFrame() OVERRIDE { EndTest(); }
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_);
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);
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);
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);
977 int times_output_surface_created_;
980 SINGLE_AND_MULTI_THREAD_TEST_F(
981 LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit);
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 {
988 static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
989 static const int kReadbackSourceFrameNumber = 1;
990 static const int kReadbackReplacementSourceFrameNumber = 2;
991 static const int kSecondOutputSurfaceInitSourceFrameNumber = 3;
993 LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw()
994 : did_react_to_first_commit_(false) {}
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;
1002 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
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)
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();
1024 return DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
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)
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)
1045 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1046 bool result) OVERRIDE {
1047 // We should only swap the first commit after the second output surface
1049 int sfn = host_impl->active_tree()->source_frame_number();
1050 EXPECT_TRUE(sfn == kSecondOutputSurfaceInitSourceFrameNumber) << sfn;
1054 virtual void AfterTest() OVERRIDE {}
1056 int did_react_to_first_commit_;
1059 MULTI_THREAD_TEST_F(
1060 LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw);
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 {
1067 static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
1068 static const int kReadbackSourceFrameNumber = 1;
1069 static const int kForcedDrawCommitSourceFrameNumber = 2;
1070 static const int kSecondOutputSurfaceInitSourceFrameNumber = 2;
1072 LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit()
1073 : did_lose_context_(false) {}
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;
1081 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
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)
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;
1101 // Returning false will result in a forced draw.
1102 return DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
1105 virtual void DidInitializeOutputSurface() OVERRIDE {
1106 if (layer_tree_host()->source_frame_number() > 0) {
1107 // Perform a readback right after the second output surface
1110 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
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)
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)
1132 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1133 bool result) OVERRIDE {
1134 // We should only swap the first commit after the second output surface
1136 int sfn = host_impl->active_tree()->source_frame_number();
1137 EXPECT_TRUE(sfn == kForcedDrawCommitSourceFrameNumber) << sfn;
1141 virtual void AfterTest() OVERRIDE {}
1143 int did_lose_context_;
1146 MULTI_THREAD_TEST_F(
1147 LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit);
1149 class ImplSidePaintingLayerTreeHostContextTest
1150 : public LayerTreeHostContextTest {
1152 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1153 settings->impl_side_painting = true;
1157 class LayerTreeHostContextTestImplSidePainting
1158 : public ImplSidePaintingLayerTreeHostContextTest {
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);
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);
1172 layer_tree_host()->SetRootLayer(root);
1173 LayerTreeHostContextTest::SetupTree();
1176 virtual void BeginTest() OVERRIDE {
1177 times_to_lose_during_commit_ = 1;
1178 PostSetNeedsCommitToMainThread();
1181 virtual void AfterTest() OVERRIDE {}
1183 virtual void DidInitializeOutputSurface() OVERRIDE { EndTest(); }
1186 FakeContentLayerClient client_;
1189 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
1191 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1193 ScrollbarLayerLostContext() : commits_(0) {}
1195 virtual void BeginTest() OVERRIDE {
1196 scoped_refptr<Layer> scroll_layer = Layer::Create();
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();
1205 virtual void AfterTest() OVERRIDE {}
1207 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1208 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1213 // First (regular) update, we should upload 2 resources (thumb, and
1215 EXPECT_EQ(1, scrollbar_layer_->update_count());
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());
1225 // Single thread proxy issues extra commits after context lost.
1226 // http://crbug.com/287250
1227 if (HasImplThread())
1237 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
1240 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1242 class UIResourceLostTest : public LayerTreeHostContextTest {
1244 UIResourceLostTest() : time_step_(0) {}
1245 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1246 settings->texture_id_allocation_chunk_size = 1;
1248 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1249 virtual void AfterTest() OVERRIDE {}
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
1258 virtual void StepCompleteOnMainThread(int time_step) = 0;
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(
1266 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal,
1267 base::Unretained(this),
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)));
1283 scoped_ptr<FakeScopedUIResource> ui_resource_;
1286 void StepCompleteOnMainThreadInternal(int step) {
1287 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1288 StepCompleteOnMainThread(step);
1292 class UIResourceLostTestSimple : public UIResourceLostTest {
1294 // This is called when the commit is complete and the new layer tree has been
1296 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1298 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1299 if (!layer_tree_host()->settings().impl_side_painting) {
1300 StepCompleteOnImplThread(impl);
1301 PostStepCompleteToMainThread();
1306 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1307 if (layer_tree_host()->settings().impl_side_painting) {
1308 StepCompleteOnImplThread(impl);
1309 PostStepCompleteToMainThread();
1315 // Losing context after an UI resource has been created.
1316 class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
1318 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1319 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1322 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1323 // Expects a valid UIResourceId.
1324 EXPECT_NE(0, ui_resource_->id());
1325 PostSetNeedsCommitToMainThread();
1328 // Release resource before ending the test.
1329 ui_resource_.reset();
1333 // Single thread proxy issues extra commits after context lost.
1334 // http://crbug.com/287250
1335 if (HasImplThread())
1343 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1344 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1345 switch (time_step_) {
1347 // The resource should have been created on LTHI after the commit.
1348 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1349 PostSetNeedsCommitToMainThread();
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();
1367 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
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
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 {
1380 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1382 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1385 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1386 // Lose the context on the impl thread before the commit.
1387 PostLoseContextToImplThread();
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();
1404 // Clear the manager of resources.
1405 ui_resource_.reset();
1406 PostSetNeedsCommitToMainThread();
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();
1422 // Release resource before ending the test.
1423 ui_resource_.reset();
1427 // Single thread proxy issues extra commits after context lost.
1428 // http://crbug.com/287250
1429 if (HasImplThread())
1437 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1438 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1439 switch (time_step_) {
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();
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_));
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_));
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);
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_));
1481 UIResourceId test_id0_;
1482 UIResourceId test_id1_;
1485 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
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());
1494 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1495 PostSetNeedsCommitToMainThread();
1498 test_id_ = ui_resource_->id();
1499 ui_resource_.reset();
1500 PostSetNeedsCommitToMainThread();
1503 // Release resource before ending the test.
1504 ui_resource_.reset();
1508 // Make sure no extra commits happened.
1513 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1514 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1515 switch (time_step_) {
1517 PostSetNeedsCommitToMainThread();
1520 PostSetNeedsCommitToMainThread();
1525 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1526 switch (time_step_) {
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()));
1542 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1543 LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1544 switch (time_step_) {
1546 // The pending requests on the impl-side should have been processed.
1547 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1550 // The "lost resource" callback should have been called once.
1551 EXPECT_EQ(1, ui_resource_->lost_resource_count);
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_));
1560 PostStepCompleteToMainThread();
1565 UIResourceId test_id_;
1568 TEST_F(UIResourceLostBeforeActivateTree,
1569 RunMultiThread_DirectRenderer_ImplSidePaint) {
1570 RunTest(true, false, true);
1573 TEST_F(UIResourceLostBeforeActivateTree,
1574 RunMultiThread_DelegatingRenderer_ImplSidePaint) {
1575 RunTest(true, true, true);
1578 // Resources evicted explicitly and by visibility changes.
1579 class UIResourceLostEviction : public UIResourceLostTestSimple {
1581 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1582 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1585 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1586 EXPECT_NE(0, ui_resource_->id());
1587 PostSetNeedsCommitToMainThread();
1590 // Make the tree not visible.
1591 PostSetVisibleToMainThread(false);
1594 // Release resource before ending the test.
1595 ui_resource_.reset();
1603 virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl,
1604 bool visible) OVERRIDE {
1605 TestWebGraphicsContext3D* context = TestContext();
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);
1620 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1621 TestWebGraphicsContext3D* context = TestContext();
1622 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1623 switch (time_step_) {
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());
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());
1648 // The resource should have been recreated after visibility was
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());
1660 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1662 class LayerTreeHostContextTestSurfaceCreateCallback
1663 : public LayerTreeHostContextTest {
1665 LayerTreeHostContextTestSurfaceCreateCallback()
1666 : LayerTreeHostContextTest(),
1667 layer_(FakeContentLayer::Create(&client_)) {}
1669 virtual void SetupTree() OVERRIDE {
1670 layer_->SetBounds(gfx::Size(10, 20));
1671 layer_tree_host()->SetRootLayer(layer_);
1672 LayerTreeHostContextTest::SetupTree();
1675 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1677 virtual void DidCommit() OVERRIDE {
1678 switch (layer_tree_host()->source_frame_number()) {
1680 EXPECT_EQ(1u, layer_->output_surface_created_count());
1681 layer_tree_host()->SetNeedsCommit();
1684 EXPECT_EQ(1u, layer_->output_surface_created_count());
1685 layer_tree_host()->SetNeedsCommit();
1688 EXPECT_EQ(1u, layer_->output_surface_created_count());
1691 EXPECT_EQ(2u, layer_->output_surface_created_count());
1692 layer_tree_host()->SetNeedsCommit();
1697 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1698 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1699 switch (LastCommittedSourceFrameNumber(impl)) {
1713 virtual void AfterTest() OVERRIDE {}
1716 FakeContentLayerClient client_;
1717 scoped_refptr<FakeContentLayer> layer_;
1720 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);