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
;
50 // These tests deal with losing the 3d graphics context.
51 class LayerTreeHostContextTest
: public LayerTreeTest
{
53 LayerTreeHostContextTest()
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();
69 // For sanity-checking tests, they should only call this when the
70 // context is not lost.
72 context3d_
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
73 GL_INNOCENT_CONTEXT_RESET_ARB
);
77 virtual scoped_ptr
<TestWebGraphicsContext3D
> CreateContext3d() {
78 return TestWebGraphicsContext3D::Create();
81 virtual scoped_ptr
<FakeOutputSurface
> CreateFakeOutputSurface(bool fallback
)
83 if (times_to_fail_create_
) {
84 --times_to_fail_create_
;
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());
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_
)
111 --times_to_lose_during_draw_
;
114 times_to_fail_create_
= times_to_fail_recreate_
;
115 times_to_fail_recreate_
= 0;
120 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
121 committed_at_least_once_
= true;
123 if (!times_to_lose_during_commit_
)
125 --times_to_lose_during_commit_
;
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_
; }
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
{
159 LayerTreeHostContextTestLostContextSucceeds()
160 : LayerTreeHostContextTest(),
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_
)
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
183 if (!recovered_context_
)
185 if (times_to_lose_during_commit_
)
187 if (times_to_lose_during_draw_
)
190 recovered_context_
= false;
192 InvalidateAndSetNeedsCommit();
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
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
))
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
;
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
;
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
{
291 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
292 : LayerTreeHostContextTest() {}
294 virtual void WillBeginTest() OVERRIDE
{
295 // Override and do not signal SetLayerTreeHostClientReady.
298 virtual void BeginTest() OVERRIDE
{
299 PostSetNeedsCommitToMainThread();
303 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface(bool fallback
)
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
{
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
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));
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
{
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
)
384 scoped_ptr
<FakeOutputSurface
> surface
=
385 LayerTreeHostContextTest::CreateFakeOutputSurface(fallback
);
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
{
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_
);
408 bool expect_fallback_attempt_
;
409 bool did_attempt_fallback_
;
410 int times_initialized_
;
413 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
414 : public LayerTreeHostContextTestCreateOutputSurfaceFails
{
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
425 class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
426 : public LayerTreeHostContextTestCreateOutputSurfaceFails
{
428 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback()
429 : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true) {}
432 SINGLE_AND_MULTI_THREAD_TEST_F(
433 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
);
435 class LayerTreeHostContextTestLostContextAndEvictTextures
436 : public LayerTreeHostContextTest
{
438 LayerTreeHostContextTestLostContextAndEvictTextures()
439 : LayerTreeHostContextTest(),
440 layer_(FakeContentLayer::Create(&client_
)),
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(
456 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
457 EvictTexturesOnImplThread
,
458 base::Unretained(this)));
460 DebugScopedSetImplThread
impl(proxy());
461 EvictTexturesOnImplThread();
465 void EvictTexturesOnImplThread() {
466 impl_host_
->EvictTexturesForTesting();
467 if (lose_after_evict_
)
471 virtual void DidCommitAndDrawFrame() OVERRIDE
{
472 if (num_commits_
> 1)
474 EXPECT_TRUE(layer_
->HaveBackingAt(0, 0));
478 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
479 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
480 if (num_commits_
> 1)
483 if (!lose_after_evict_
)
488 virtual void DidInitializeOutputSurface() OVERRIDE
{ EndTest(); }
490 virtual void AfterTest() OVERRIDE
{}
493 bool lose_after_evict_
;
494 FakeContentLayerClient client_
;
495 scoped_refptr
<FakeContentLayer
> layer_
;
496 LayerTreeHostImpl
* impl_host_
;
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
{
570 LayerTreeHostContextTestLostContextWhileUpdatingResources()
571 : parent_(FakeContentLayer::Create(&client_
)),
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_
);
607 virtual void AfterTest() OVERRIDE
{
608 EXPECT_EQ(0, times_to_lose_on_end_query_
);
612 FakeContentLayerClient client_
;
613 scoped_refptr
<FakeContentLayer
> parent_
;
615 int times_to_lose_on_end_query_
;
618 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
619 LayerTreeHostContextTestLostContextWhileUpdatingResources
);
621 class LayerTreeHostContextTestLayersNotified
: public LayerTreeHostContextTest
{
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]);
651 switch (num_commits_
) {
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.
658 times_to_fail_create_
= 1;
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());
671 virtual void AfterTest() OVERRIDE
{}
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
{
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(),
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.
715 gfx::Rect(0, 0, 10, 10),
716 gfx::Rect(0, 0, 10, 10),
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),
724 pass
->AppendOneOfEveryQuadType(child_resource_provider_
.get(),
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(
738 ResourceProvider::TextureHintImmutable
,
740 ResourceProvider::ScopedWriteLockGL
lock(child_resource_provider_
.get(),
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());
803 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
804 mailbox
, GL_TEXTURE_2D
, sync_point
)),
805 media::VideoFrame::ReleaseMailboxCB(),
807 gfx::Rect(0, 0, 4, 4),
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(),
816 gfx::Rect(0, 0, 3, 2),
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
);
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);
876 virtual scoped_ptr
<FakeOutputSurface
> CreateFakeOutputSurface(bool fallback
)
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();
898 virtual void AfterTest() OVERRIDE
{ EXPECT_TRUE(lost_context_
); }
901 FakeContentLayerClient client_
;
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
{
927 virtual void InitializeSettings(LayerTreeSettings
* settings
) OVERRIDE
{
928 settings
->impl_side_painting
= true;
932 class LayerTreeHostContextTestImplSidePainting
933 : public ImplSidePaintingLayerTreeHostContextTest
{
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(); }
959 FakeContentLayerClient client_
;
962 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting
);
964 class ScrollbarLayerLostContext
: public LayerTreeHostContextTest
{
966 ScrollbarLayerLostContext() : commits_(0) {}
968 virtual void BeginTest() OVERRIDE
{
969 scoped_refptr
<Layer
> scroll_layer
= Layer::Create();
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
);
986 // First (regular) update, we should upload 2 resources (thumb, and
988 EXPECT_EQ(1, scrollbar_layer_
->update_count());
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());
1004 scoped_refptr
<FakePaintedScrollbarLayer
> scrollbar_layer_
;
1007 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext
);
1009 class UIResourceLostTest
: public LayerTreeHostContextTest
{
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
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(
1033 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal
,
1034 base::Unretained(this),
1038 void PostLoseContextToImplThread() {
1039 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1040 ImplThreadTaskRunner()->PostTask(
1042 base::Bind(&LayerTreeHostContextTest::LoseContext
,
1043 base::Unretained(this)));
1048 scoped_ptr
<FakeScopedUIResource
> ui_resource_
;
1051 void StepCompleteOnMainThreadInternal(int step
) {
1052 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1053 StepCompleteOnMainThread(step
);
1057 class UIResourceLostTestSimple
: public UIResourceLostTest
{
1059 // This is called when the commit is complete and the new layer tree has been
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();
1071 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1072 if (layer_tree_host()->settings().impl_side_painting
) {
1073 StepCompleteOnImplThread(impl
);
1074 PostStepCompleteToMainThread();
1080 // Losing context after an UI resource has been created.
1081 class UIResourceLostAfterCommit
: public UIResourceLostTestSimple
{
1083 virtual void StepCompleteOnMainThread(int step
) OVERRIDE
{
1084 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1087 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1088 // Expects a valid UIResourceId.
1089 EXPECT_NE(0, ui_resource_
->id());
1090 PostSetNeedsCommitToMainThread();
1093 // Release resource before ending the test.
1094 ui_resource_
.reset();
1103 virtual void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1104 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1105 switch (time_step_
) {
1107 // The resource should have been created on LTHI after the commit.
1108 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1109 PostSetNeedsCommitToMainThread();
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();
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
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
{
1140 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1142 virtual void StepCompleteOnMainThread(int step
) OVERRIDE
{
1145 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1146 // Lose the context on the impl thread before the commit.
1147 PostLoseContextToImplThread();
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();
1164 // Clear the manager of resources.
1165 ui_resource_
.reset();
1166 PostSetNeedsCommitToMainThread();
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();
1182 // Release resource before ending the test.
1183 ui_resource_
.reset();
1192 virtual void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1193 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1194 switch (time_step_
) {
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();
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
);
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_
));
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());
1242 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1243 PostSetNeedsCommitToMainThread();
1246 test_id_
= ui_resource_
->id();
1247 ui_resource_
.reset();
1248 PostSetNeedsCommitToMainThread();
1251 // Release resource before ending the test.
1252 ui_resource_
.reset();
1256 // Make sure no extra commits happened.
1261 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1262 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1263 switch (time_step_
) {
1265 PostSetNeedsCommitToMainThread();
1268 PostSetNeedsCommitToMainThread();
1273 virtual void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1274 switch (time_step_
) {
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()));
1290 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1291 LayerTreeHostContextTest::DidActivateTreeOnThread(impl
);
1292 switch (time_step_
) {
1294 // The pending requests on the impl-side should have been processed.
1295 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1298 // The "lost resource" callback should have been called once.
1299 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
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_
));
1308 PostStepCompleteToMainThread();
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
{
1329 virtual void StepCompleteOnMainThread(int step
) OVERRIDE
{
1330 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1333 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1334 EXPECT_NE(0, ui_resource_
->id());
1335 PostSetNeedsCommitToMainThread();
1338 // Make the tree not visible.
1339 PostSetVisibleToMainThread(false);
1342 // Release resource before ending the test.
1343 ui_resource_
.reset();
1351 virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl
* impl
,
1352 bool visible
) OVERRIDE
{
1353 TestWebGraphicsContext3D
* context
= TestContext();
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_
) {
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());
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());
1396 // The resource should have been recreated after visibility was
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());
1408 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction
);
1410 class LayerTreeHostContextTestSurfaceCreateCallback
1411 : public LayerTreeHostContextTest
{
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()) {
1428 EXPECT_EQ(1u, layer_
->output_surface_created_count());
1429 layer_tree_host()->SetNeedsCommit();
1432 EXPECT_EQ(1u, layer_
->output_surface_created_count());
1433 layer_tree_host()->SetNeedsCommit();
1436 EXPECT_EQ(1u, layer_
->output_surface_created_count());
1439 EXPECT_EQ(2u, layer_
->output_surface_created_count());
1440 layer_tree_host()->SetNeedsCommit();
1445 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1446 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1447 switch (LastCommittedSourceFrameNumber(impl
)) {
1461 virtual void AfterTest() OVERRIDE
{}
1464 FakeContentLayerClient client_
;
1465 scoped_refptr
<FakeContentLayer
> layer_
;
1468 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback
);
1470 class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
1471 : public LayerTreeHostContextTest
{
1473 virtual void BeginTest() OVERRIDE
{
1475 PostSetNeedsCommitToMainThread();
1478 virtual void ScheduledActionWillSendBeginMainFrame() OVERRIDE
{
1483 // Defer commits before the BeginFrame arrives, causing it to be delayed.
1484 MainThreadTaskRunner()->PostTask(
1486 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1487 DeferCommitsOnMainThread
,
1488 base::Unretained(this),
1490 // Meanwhile, lose the context while we are in defer commits.
1491 ImplThreadTaskRunner()->PostTask(
1493 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1494 LoseContextOnImplThread
,
1495 base::Unretained(this)));
1498 void LoseContextOnImplThread() {
1501 // After losing the context, stop deferring commits.
1502 MainThreadTaskRunner()->PostTask(
1504 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1505 DeferCommitsOnMainThread
,
1506 base::Unretained(this),
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
{}
1526 SINGLE_AND_MULTI_THREAD_TEST_F(
1527 LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
);