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 DrawResult
PrepareToDrawOnThread(
100 LayerTreeHostImpl
* host_impl
,
101 LayerTreeHostImpl::FrameData
* frame
,
102 DrawResult draw_result
) OVERRIDE
{
103 EXPECT_EQ(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_
->SetIsDrawable(true);
313 content_
= FakeContentLayer::Create(&client_
);
314 content_
->SetBounds(gfx::Size(10, 10));
315 content_
->SetIsDrawable(true);
317 root_
->AddChild(content_
);
319 layer_tree_host()->SetRootLayer(root_
);
320 LayerTreeHostContextTest::SetupTree();
323 virtual void InvalidateAndSetNeedsCommit() OVERRIDE
{
324 // Invalidate the render surface so we don't try to use a cached copy of the
325 // surface. We want to make sure to test the drawing paths for drawing to
327 content_
->SetNeedsDisplay();
328 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
331 virtual void DrawLayersOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
332 FakeContentLayerImpl
* content_impl
= static_cast<FakeContentLayerImpl
*>(
333 host_impl
->active_tree()->root_layer()->children()[0]);
334 // Even though the context was lost, we should have a resource. The
335 // TestWebGraphicsContext3D ensures that this resource is created with
336 // the active context.
337 EXPECT_TRUE(content_impl
->HaveResourceForTileAt(0, 0));
341 FakeContentLayerClient client_
;
342 scoped_refptr
<Layer
> root_
;
343 scoped_refptr
<ContentLayer
> content_
;
346 // This test uses TiledLayer to check for a working context.
347 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
348 LayerTreeHostContextTestLostContextSucceedsWithContent
);
350 class LayerTreeHostContextTestCreateOutputSurfaceFails
351 : public LayerTreeHostContextTest
{
353 // Run a test that initially fails OutputSurface creation |times_to_fail|
354 // times. If |expect_fallback_attempt| is |true|, an attempt to create a
355 // fallback/software OutputSurface is expected to occur.
356 LayerTreeHostContextTestCreateOutputSurfaceFails(int times_to_fail
,
357 bool expect_fallback_attempt
)
358 : times_to_fail_(times_to_fail
),
359 expect_fallback_attempt_(expect_fallback_attempt
),
360 did_attempt_fallback_(false),
361 times_initialized_(0) {}
363 virtual void BeginTest() OVERRIDE
{
364 times_to_fail_create_
= times_to_fail_
;
365 PostSetNeedsCommitToMainThread();
368 virtual scoped_ptr
<FakeOutputSurface
> CreateFakeOutputSurface(bool fallback
)
370 scoped_ptr
<FakeOutputSurface
> surface
=
371 LayerTreeHostContextTest::CreateFakeOutputSurface(fallback
);
374 EXPECT_EQ(times_to_fail_
, times_create_failed_
);
376 did_attempt_fallback_
= fallback
;
377 return surface
.Pass();
380 virtual void DidInitializeOutputSurface() OVERRIDE
{ times_initialized_
++; }
382 virtual void DrawLayersOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
386 virtual void AfterTest() OVERRIDE
{
387 EXPECT_EQ(times_to_fail_
, times_create_failed_
);
388 EXPECT_NE(0, times_initialized_
);
389 EXPECT_EQ(expect_fallback_attempt_
, did_attempt_fallback_
);
394 bool expect_fallback_attempt_
;
395 bool did_attempt_fallback_
;
396 int times_initialized_
;
399 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
400 : public LayerTreeHostContextTestCreateOutputSurfaceFails
{
402 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
403 : LayerTreeHostContextTestCreateOutputSurfaceFails(1, false) {}
406 SINGLE_AND_MULTI_THREAD_TEST_F(
407 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
);
409 // After 4 failures we expect an attempt to create a fallback/software
411 class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
412 : public LayerTreeHostContextTestCreateOutputSurfaceFails
{
414 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback()
415 : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true) {}
418 SINGLE_AND_MULTI_THREAD_TEST_F(
419 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
);
421 class LayerTreeHostContextTestLostContextAndEvictTextures
422 : public LayerTreeHostContextTest
{
424 LayerTreeHostContextTestLostContextAndEvictTextures()
425 : LayerTreeHostContextTest(),
426 layer_(FakeContentLayer::Create(&client_
)),
430 virtual void SetupTree() OVERRIDE
{
431 layer_
->SetBounds(gfx::Size(10, 20));
432 layer_tree_host()->SetRootLayer(layer_
);
433 LayerTreeHostContextTest::SetupTree();
436 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
438 void PostEvictTextures() {
439 if (HasImplThread()) {
440 ImplThreadTaskRunner()->PostTask(
442 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
443 EvictTexturesOnImplThread
,
444 base::Unretained(this)));
446 DebugScopedSetImplThread
impl(proxy());
447 EvictTexturesOnImplThread();
451 void EvictTexturesOnImplThread() {
452 impl_host_
->EvictTexturesForTesting();
453 if (lose_after_evict_
)
457 virtual void DidCommitAndDrawFrame() OVERRIDE
{
458 if (num_commits_
> 1)
460 EXPECT_TRUE(layer_
->HaveBackingAt(0, 0));
464 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
465 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
466 if (num_commits_
> 1)
469 if (!lose_after_evict_
)
474 virtual void DidInitializeOutputSurface() OVERRIDE
{ EndTest(); }
476 virtual void AfterTest() OVERRIDE
{}
479 bool lose_after_evict_
;
480 FakeContentLayerClient client_
;
481 scoped_refptr
<FakeContentLayer
> layer_
;
482 LayerTreeHostImpl
* impl_host_
;
486 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
487 LoseAfterEvict_SingleThread_DirectRenderer
) {
488 lose_after_evict_
= true;
489 RunTest(false, false, false);
492 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
493 LoseAfterEvict_SingleThread_DelegatingRenderer
) {
494 lose_after_evict_
= true;
495 RunTest(false, true, false);
498 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
499 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint
) {
500 lose_after_evict_
= true;
501 RunTest(true, false, false);
504 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
505 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint
) {
506 lose_after_evict_
= true;
507 RunTest(true, true, false);
510 // Flaky on all platforms, http://crbug.com/310979
511 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
512 DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint
) {
513 lose_after_evict_
= true;
514 RunTest(true, true, true);
517 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
518 LoseBeforeEvict_SingleThread_DirectRenderer
) {
519 lose_after_evict_
= false;
520 RunTest(false, false, false);
523 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
524 LoseBeforeEvict_SingleThread_DelegatingRenderer
) {
525 lose_after_evict_
= false;
526 RunTest(false, true, false);
529 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
530 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint
) {
531 lose_after_evict_
= false;
532 RunTest(true, false, false);
535 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
536 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint
) {
537 lose_after_evict_
= false;
538 RunTest(true, false, true);
541 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
542 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint
) {
543 lose_after_evict_
= false;
544 RunTest(true, true, false);
547 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
548 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint
) {
549 lose_after_evict_
= false;
550 RunTest(true, true, true);
553 class LayerTreeHostContextTestLostContextWhileUpdatingResources
554 : public LayerTreeHostContextTest
{
556 LayerTreeHostContextTestLostContextWhileUpdatingResources()
557 : parent_(FakeContentLayer::Create(&client_
)),
559 times_to_lose_on_end_query_(3) {}
561 virtual scoped_ptr
<TestWebGraphicsContext3D
> CreateContext3d() OVERRIDE
{
562 scoped_ptr
<TestWebGraphicsContext3D
> context
=
563 LayerTreeHostContextTest::CreateContext3d();
564 if (times_to_lose_on_end_query_
) {
565 --times_to_lose_on_end_query_
;
566 context
->set_times_end_query_succeeds(5);
568 return context
.Pass();
571 virtual void SetupTree() OVERRIDE
{
572 parent_
->SetBounds(gfx::Size(num_children_
, 1));
574 for (int i
= 0; i
< num_children_
; i
++) {
575 scoped_refptr
<FakeContentLayer
> child
=
576 FakeContentLayer::Create(&client_
);
577 child
->SetPosition(gfx::PointF(i
, 0.f
));
578 child
->SetBounds(gfx::Size(1, 1));
579 parent_
->AddChild(child
);
582 layer_tree_host()->SetRootLayer(parent_
);
583 LayerTreeHostContextTest::SetupTree();
586 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
588 virtual void DrawLayersOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
589 EXPECT_EQ(0, times_to_lose_on_end_query_
);
593 virtual void AfterTest() OVERRIDE
{
594 EXPECT_EQ(0, times_to_lose_on_end_query_
);
598 FakeContentLayerClient client_
;
599 scoped_refptr
<FakeContentLayer
> parent_
;
601 int times_to_lose_on_end_query_
;
604 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
605 LayerTreeHostContextTestLostContextWhileUpdatingResources
);
607 class LayerTreeHostContextTestLayersNotified
: public LayerTreeHostContextTest
{
609 LayerTreeHostContextTestLayersNotified()
610 : LayerTreeHostContextTest(), num_commits_(0) {}
612 virtual void SetupTree() OVERRIDE
{
613 root_
= FakeContentLayer::Create(&client_
);
614 child_
= FakeContentLayer::Create(&client_
);
615 grandchild_
= FakeContentLayer::Create(&client_
);
617 root_
->AddChild(child_
);
618 child_
->AddChild(grandchild_
);
620 layer_tree_host()->SetRootLayer(root_
);
621 LayerTreeHostContextTest::SetupTree();
624 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
626 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
627 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl
);
629 FakeContentLayerImpl
* root
= static_cast<FakeContentLayerImpl
*>(
630 host_impl
->active_tree()->root_layer());
631 FakeContentLayerImpl
* child
=
632 static_cast<FakeContentLayerImpl
*>(root
->children()[0]);
633 FakeContentLayerImpl
* grandchild
=
634 static_cast<FakeContentLayerImpl
*>(child
->children()[0]);
637 switch (num_commits_
) {
639 EXPECT_EQ(0u, root
->lost_output_surface_count());
640 EXPECT_EQ(0u, child
->lost_output_surface_count());
641 EXPECT_EQ(0u, grandchild
->lost_output_surface_count());
642 // Lose the context and struggle to recreate it.
644 times_to_fail_create_
= 1;
647 EXPECT_GE(1u, root
->lost_output_surface_count());
648 EXPECT_GE(1u, child
->lost_output_surface_count());
649 EXPECT_GE(1u, grandchild
->lost_output_surface_count());
657 virtual void AfterTest() OVERRIDE
{}
662 FakeContentLayerClient client_
;
663 scoped_refptr
<FakeContentLayer
> root_
;
664 scoped_refptr
<FakeContentLayer
> child_
;
665 scoped_refptr
<FakeContentLayer
> grandchild_
;
668 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified
);
670 class LayerTreeHostContextTestDontUseLostResources
671 : public LayerTreeHostContextTest
{
673 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
674 context_should_support_io_surface_
= true;
676 child_output_surface_
= FakeOutputSurface::Create3d();
677 child_output_surface_
->BindToClient(&output_surface_client_
);
678 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
679 child_resource_provider_
= ResourceProvider::Create(
680 child_output_surface_
.get(), shared_bitmap_manager_
.get(), 0, false, 1,
684 static void EmptyReleaseCallback(unsigned sync_point
, bool lost
) {}
686 virtual void SetupTree() OVERRIDE
{
687 gpu::gles2::GLES2Interface
* gl
=
688 child_output_surface_
->context_provider()->ContextGL();
690 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
692 scoped_ptr
<TestRenderPass
> pass_for_quad
= TestRenderPass::Create();
693 pass_for_quad
->SetNew(
694 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
695 RenderPass::Id(2, 1),
696 gfx::Rect(0, 0, 10, 10),
697 gfx::Rect(0, 0, 10, 10),
700 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
701 pass
->SetNew(RenderPass::Id(1, 1),
702 gfx::Rect(0, 0, 10, 10),
703 gfx::Rect(0, 0, 10, 10),
705 pass
->AppendOneOfEveryQuadType(child_resource_provider_
.get(),
706 RenderPass::Id(2, 1));
708 frame_data
->render_pass_list
.push_back(pass_for_quad
.PassAs
<RenderPass
>());
709 frame_data
->render_pass_list
.push_back(pass
.PassAs
<RenderPass
>());
711 delegated_resource_collection_
= new DelegatedFrameResourceCollection
;
712 delegated_frame_provider_
= new DelegatedFrameProvider(
713 delegated_resource_collection_
.get(), frame_data
.Pass());
715 ResourceProvider::ResourceId resource
=
716 child_resource_provider_
->CreateResource(
719 ResourceProvider::TextureUsageAny
,
721 ResourceProvider::ScopedWriteLockGL
lock(child_resource_provider_
.get(),
724 gpu::Mailbox mailbox
;
725 gl
->GenMailboxCHROMIUM(mailbox
.name
);
726 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
728 scoped_refptr
<Layer
> root
= Layer::Create();
729 root
->SetBounds(gfx::Size(10, 10));
730 root
->SetIsDrawable(true);
732 scoped_refptr
<FakeDelegatedRendererLayer
> delegated
=
733 FakeDelegatedRendererLayer::Create(delegated_frame_provider_
.get());
734 delegated
->SetBounds(gfx::Size(10, 10));
735 delegated
->SetIsDrawable(true);
736 root
->AddChild(delegated
);
738 scoped_refptr
<ContentLayer
> content
= ContentLayer::Create(&client_
);
739 content
->SetBounds(gfx::Size(10, 10));
740 content
->SetIsDrawable(true);
741 root
->AddChild(content
);
743 scoped_refptr
<TextureLayer
> texture
= TextureLayer::CreateForMailbox(NULL
);
744 texture
->SetBounds(gfx::Size(10, 10));
745 texture
->SetIsDrawable(true);
746 texture
->SetTextureMailbox(
747 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
748 SingleReleaseCallback::Create(
749 base::Bind(&LayerTreeHostContextTestDontUseLostResources::
750 EmptyReleaseCallback
)));
751 root
->AddChild(texture
);
753 scoped_refptr
<ContentLayer
> mask
= ContentLayer::Create(&client_
);
754 mask
->SetBounds(gfx::Size(10, 10));
756 scoped_refptr
<ContentLayer
> content_with_mask
=
757 ContentLayer::Create(&client_
);
758 content_with_mask
->SetBounds(gfx::Size(10, 10));
759 content_with_mask
->SetIsDrawable(true);
760 content_with_mask
->SetMaskLayer(mask
.get());
761 root
->AddChild(content_with_mask
);
763 scoped_refptr
<VideoLayer
> video_color
=
764 VideoLayer::Create(&color_frame_provider_
);
765 video_color
->SetBounds(gfx::Size(10, 10));
766 video_color
->SetIsDrawable(true);
767 root
->AddChild(video_color
);
769 scoped_refptr
<VideoLayer
> video_hw
=
770 VideoLayer::Create(&hw_frame_provider_
);
771 video_hw
->SetBounds(gfx::Size(10, 10));
772 video_hw
->SetIsDrawable(true);
773 root
->AddChild(video_hw
);
775 scoped_refptr
<VideoLayer
> video_scaled_hw
=
776 VideoLayer::Create(&scaled_hw_frame_provider_
);
777 video_scaled_hw
->SetBounds(gfx::Size(10, 10));
778 video_scaled_hw
->SetIsDrawable(true);
779 root
->AddChild(video_scaled_hw
);
781 color_video_frame_
= VideoFrame::CreateColorFrame(
782 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
784 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
785 mailbox
, GL_TEXTURE_2D
, sync_point
)),
786 media::VideoFrame::ReleaseMailboxCB(),
788 gfx::Rect(0, 0, 4, 4),
791 VideoFrame::ReadPixelsCB());
792 scaled_hw_video_frame_
=
793 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
794 mailbox
, GL_TEXTURE_2D
, sync_point
)),
795 media::VideoFrame::ReleaseMailboxCB(),
797 gfx::Rect(0, 0, 3, 2),
800 VideoFrame::ReadPixelsCB());
802 color_frame_provider_
.set_frame(color_video_frame_
);
803 hw_frame_provider_
.set_frame(hw_video_frame_
);
804 scaled_hw_frame_provider_
.set_frame(scaled_hw_video_frame_
);
806 if (!delegating_renderer()) {
807 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
808 scoped_refptr
<IOSurfaceLayer
> io_surface
= IOSurfaceLayer::Create();
809 io_surface
->SetBounds(gfx::Size(10, 10));
810 io_surface
->SetIsDrawable(true);
811 io_surface
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
812 root
->AddChild(io_surface
);
816 LayerTreeDebugState debug_state
;
817 debug_state
.show_property_changed_rects
= true;
818 layer_tree_host()->SetDebugState(debug_state
);
820 scoped_refptr
<PaintedScrollbarLayer
> scrollbar
=
821 PaintedScrollbarLayer::Create(
822 scoped_ptr
<Scrollbar
>(new FakeScrollbar
).Pass(), content
->id());
823 scrollbar
->SetBounds(gfx::Size(10, 10));
824 scrollbar
->SetIsDrawable(true);
825 root
->AddChild(scrollbar
);
827 layer_tree_host()->SetRootLayer(root
);
828 LayerTreeHostContextTest::SetupTree();
831 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
833 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) OVERRIDE
{
834 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl
);
836 if (host_impl
->active_tree()->source_frame_number() == 3) {
837 // On the third commit we're recovering from context loss. Hardware
838 // video frames should not be reused by the VideoFrameProvider, but
839 // software frames can be.
840 hw_frame_provider_
.set_frame(NULL
);
841 scaled_hw_frame_provider_
.set_frame(NULL
);
845 virtual DrawResult
PrepareToDrawOnThread(
846 LayerTreeHostImpl
* host_impl
,
847 LayerTreeHostImpl::FrameData
* frame
,
848 DrawResult draw_result
) OVERRIDE
{
849 if (host_impl
->active_tree()->source_frame_number() == 2) {
850 // Lose the context during draw on the second commit. This will cause
851 // a third commit to recover.
852 context3d_
->set_times_bind_texture_succeeds(0);
857 virtual scoped_ptr
<FakeOutputSurface
> CreateFakeOutputSurface(bool fallback
)
859 // This will get called twice:
860 // First when we create the initial output surface...
861 if (layer_tree_host()->source_frame_number() > 0) {
862 // ... and then again after we forced the context to be lost.
863 lost_context_
= true;
865 return LayerTreeHostContextTest::CreateFakeOutputSurface(fallback
);
868 virtual void DidCommitAndDrawFrame() OVERRIDE
{
869 ASSERT_TRUE(layer_tree_host()->hud_layer());
870 // End the test once we know the 3nd frame drew.
871 if (layer_tree_host()->source_frame_number() < 5) {
872 layer_tree_host()->root_layer()->SetNeedsDisplay();
873 layer_tree_host()->SetNeedsCommit();
879 virtual void AfterTest() OVERRIDE
{ EXPECT_TRUE(lost_context_
); }
882 FakeContentLayerClient client_
;
885 FakeOutputSurfaceClient output_surface_client_
;
886 scoped_ptr
<FakeOutputSurface
> child_output_surface_
;
887 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
888 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
890 scoped_refptr
<DelegatedFrameResourceCollection
>
891 delegated_resource_collection_
;
892 scoped_refptr
<DelegatedFrameProvider
> delegated_frame_provider_
;
894 scoped_refptr
<VideoFrame
> color_video_frame_
;
895 scoped_refptr
<VideoFrame
> hw_video_frame_
;
896 scoped_refptr
<VideoFrame
> scaled_hw_video_frame_
;
898 FakeVideoFrameProvider color_frame_provider_
;
899 FakeVideoFrameProvider hw_frame_provider_
;
900 FakeVideoFrameProvider scaled_hw_frame_provider_
;
903 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources
);
905 class ImplSidePaintingLayerTreeHostContextTest
906 : public LayerTreeHostContextTest
{
908 virtual void InitializeSettings(LayerTreeSettings
* settings
) OVERRIDE
{
909 settings
->impl_side_painting
= true;
913 class LayerTreeHostContextTestImplSidePainting
914 : public ImplSidePaintingLayerTreeHostContextTest
{
916 virtual void SetupTree() OVERRIDE
{
917 scoped_refptr
<Layer
> root
= Layer::Create();
918 root
->SetBounds(gfx::Size(10, 10));
919 root
->SetIsDrawable(true);
921 scoped_refptr
<PictureLayer
> picture
= PictureLayer::Create(&client_
);
922 picture
->SetBounds(gfx::Size(10, 10));
923 picture
->SetIsDrawable(true);
924 root
->AddChild(picture
);
926 layer_tree_host()->SetRootLayer(root
);
927 LayerTreeHostContextTest::SetupTree();
930 virtual void BeginTest() OVERRIDE
{
931 times_to_lose_during_commit_
= 1;
932 PostSetNeedsCommitToMainThread();
935 virtual void AfterTest() OVERRIDE
{}
937 virtual void DidInitializeOutputSurface() OVERRIDE
{ EndTest(); }
940 FakeContentLayerClient client_
;
943 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting
);
945 class ScrollbarLayerLostContext
: public LayerTreeHostContextTest
{
947 ScrollbarLayerLostContext() : commits_(0) {}
949 virtual void BeginTest() OVERRIDE
{
950 scoped_refptr
<Layer
> scroll_layer
= Layer::Create();
952 FakePaintedScrollbarLayer::Create(false, true, scroll_layer
->id());
953 scrollbar_layer_
->SetBounds(gfx::Size(10, 100));
954 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_
);
955 layer_tree_host()->root_layer()->AddChild(scroll_layer
);
956 PostSetNeedsCommitToMainThread();
959 virtual void AfterTest() OVERRIDE
{}
961 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
962 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
967 // First (regular) update, we should upload 2 resources (thumb, and
969 EXPECT_EQ(1, scrollbar_layer_
->update_count());
973 // Second update, after the lost context, we should still upload 2
974 // resources even if the contents haven't changed.
975 EXPECT_EQ(2, scrollbar_layer_
->update_count());
979 // Single thread proxy issues extra commits after context lost.
980 // http://crbug.com/287250
991 scoped_refptr
<FakePaintedScrollbarLayer
> scrollbar_layer_
;
994 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext
);
996 class UIResourceLostTest
: public LayerTreeHostContextTest
{
998 UIResourceLostTest() : time_step_(0) {}
999 virtual void InitializeSettings(LayerTreeSettings
* settings
) OVERRIDE
{
1000 settings
->texture_id_allocation_chunk_size
= 1;
1002 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
1003 virtual void AfterTest() OVERRIDE
{}
1005 // This is called on the main thread after each commit and
1006 // DidActivateTreeOnThread, with the value of time_step_ at the time
1007 // of the call to DidActivateTreeOnThread. Similar tests will do
1008 // work on the main thread in DidCommit but that is unsuitable because
1009 // the main thread work for these tests must happen after
1010 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1012 virtual void StepCompleteOnMainThread(int time_step
) = 0;
1014 // Called after DidActivateTreeOnThread. If this is done during the commit,
1015 // the call to StepCompleteOnMainThread will not occur until after
1016 // the commit completes, because the main thread is blocked.
1017 void PostStepCompleteToMainThread() {
1018 proxy()->MainThreadTaskRunner()->PostTask(
1020 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal
,
1021 base::Unretained(this),
1025 void PostLoseContextToImplThread() {
1026 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1027 base::SingleThreadTaskRunner
* task_runner
=
1028 HasImplThread() ? ImplThreadTaskRunner()
1029 : base::MessageLoopProxy::current();
1030 task_runner
->PostTask(FROM_HERE
,
1031 base::Bind(&LayerTreeHostContextTest::LoseContext
,
1032 base::Unretained(this)));
1037 scoped_ptr
<FakeScopedUIResource
> ui_resource_
;
1040 void StepCompleteOnMainThreadInternal(int step
) {
1041 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1042 StepCompleteOnMainThread(step
);
1046 class UIResourceLostTestSimple
: public UIResourceLostTest
{
1048 // This is called when the commit is complete and the new layer tree has been
1050 virtual void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) = 0;
1052 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1053 if (!layer_tree_host()->settings().impl_side_painting
) {
1054 StepCompleteOnImplThread(impl
);
1055 PostStepCompleteToMainThread();
1060 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1061 if (layer_tree_host()->settings().impl_side_painting
) {
1062 StepCompleteOnImplThread(impl
);
1063 PostStepCompleteToMainThread();
1069 // Losing context after an UI resource has been created.
1070 class UIResourceLostAfterCommit
: public UIResourceLostTestSimple
{
1072 virtual void StepCompleteOnMainThread(int step
) OVERRIDE
{
1073 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1076 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1077 // Expects a valid UIResourceId.
1078 EXPECT_NE(0, ui_resource_
->id());
1079 PostSetNeedsCommitToMainThread();
1082 // Release resource before ending the test.
1083 ui_resource_
.reset();
1087 // Single thread proxy issues extra commits after context lost.
1088 // http://crbug.com/287250
1089 if (HasImplThread())
1097 virtual void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1098 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1099 switch (time_step_
) {
1101 // The resource should have been created on LTHI after the commit.
1102 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1103 PostSetNeedsCommitToMainThread();
1109 // The resources should have been recreated. The bitmap callback should
1110 // have been called once with the resource_lost flag set to true.
1111 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1112 // Resource Id on the impl-side have been recreated as well. Note
1113 // that the same UIResourceId persists after the context lost.
1114 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1115 PostSetNeedsCommitToMainThread();
1121 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit
);
1123 // Losing context before UI resource requests can be commited. Three sequences
1124 // of creation/deletion are considered:
1125 // 1. Create one resource -> Context Lost => Expect the resource to have been
1127 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1128 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1129 // test_id1_ to have been created.
1130 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1131 // the resource to not exist in the manager.
1132 class UIResourceLostBeforeCommit
: public UIResourceLostTestSimple
{
1134 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1136 virtual void StepCompleteOnMainThread(int step
) OVERRIDE
{
1139 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1140 // Lose the context on the impl thread before the commit.
1141 PostLoseContextToImplThread();
1145 // Currently one resource has been created.
1146 test_id0_
= ui_resource_
->id();
1147 // Delete this resource.
1148 ui_resource_
.reset();
1149 // Create another resource.
1150 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1151 test_id1_
= ui_resource_
->id();
1152 // Sanity check that two resource creations return different ids.
1153 EXPECT_NE(test_id0_
, test_id1_
);
1154 // Lose the context on the impl thread before the commit.
1155 PostLoseContextToImplThread();
1158 // Clear the manager of resources.
1159 ui_resource_
.reset();
1160 PostSetNeedsCommitToMainThread();
1164 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1165 test_id0_
= ui_resource_
->id();
1166 // Sanity check the UIResourceId should not be 0.
1167 EXPECT_NE(0, test_id0_
);
1168 // Usually ScopedUIResource are deleted from the manager in their
1169 // destructor (so usually ui_resource_.reset()). But here we need
1170 // ui_resource_ for the next step, so call DeleteUIResource directly.
1171 layer_tree_host()->DeleteUIResource(test_id0_
);
1172 // Delete the resouce and then lose the context.
1173 PostLoseContextToImplThread();
1176 // Release resource before ending the test.
1177 ui_resource_
.reset();
1181 // Single thread proxy issues extra commits after context lost.
1182 // http://crbug.com/287250
1183 if (HasImplThread())
1191 virtual void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1192 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1193 switch (time_step_
) {
1195 // Sequence 1 (continued):
1196 // The first context lost happens before the resources were created,
1197 // and because it resulted in no resources being destroyed, it does not
1198 // trigger resource re-creation.
1199 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1200 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1201 // Resource Id on the impl-side has been created.
1202 PostSetNeedsCommitToMainThread();
1205 // Sequence 2 (continued):
1206 // The previous resource should have been deleted.
1207 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(test_id0_
));
1208 if (HasImplThread()) {
1209 // The second resource should have been created.
1210 EXPECT_NE(0u, impl
->ResourceIdForUIResource(test_id1_
));
1212 // The extra commit that happens at context lost in the single thread
1213 // proxy changes the timing so that the resource has been destroyed.
1214 // http://crbug.com/287250
1215 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(test_id1_
));
1217 // The second resource called the resource callback once and since the
1218 // context is lost, a "resource lost" callback was also issued.
1219 EXPECT_EQ(2, ui_resource_
->resource_create_count
);
1220 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1223 // Sequence 3 (continued):
1224 // Expect the resource callback to have been called once.
1225 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1226 // No "resource lost" callbacks.
1227 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1228 // The UI resource id should not be valid
1229 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(test_id0_
));
1235 UIResourceId test_id0_
;
1236 UIResourceId test_id1_
;
1239 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit
);
1241 // Losing UI resource before the pending trees is activated but after the
1242 // commit. Impl-side-painting only.
1243 class UIResourceLostBeforeActivateTree
: public UIResourceLostTest
{
1244 virtual void StepCompleteOnMainThread(int step
) OVERRIDE
{
1245 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1248 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1249 PostSetNeedsCommitToMainThread();
1252 test_id_
= ui_resource_
->id();
1253 ui_resource_
.reset();
1254 PostSetNeedsCommitToMainThread();
1257 // Release resource before ending the test.
1258 ui_resource_
.reset();
1262 // Make sure no extra commits happened.
1267 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1268 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1269 switch (time_step_
) {
1271 PostSetNeedsCommitToMainThread();
1274 PostSetNeedsCommitToMainThread();
1279 virtual void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1280 switch (time_step_
) {
1282 // The resource creation callback has been called.
1283 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1284 // The resource is not yet lost (sanity check).
1285 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1286 // The resource should not have been created yet on the impl-side.
1287 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1296 virtual void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1297 LayerTreeHostContextTest::DidActivateTreeOnThread(impl
);
1298 switch (time_step_
) {
1300 // The pending requests on the impl-side should have been processed.
1301 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1304 // The "lost resource" callback should have been called once.
1305 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1308 // The resource is deleted and should not be in the manager. Use
1309 // test_id_ since ui_resource_ has been deleted.
1310 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(test_id_
));
1314 PostStepCompleteToMainThread();
1319 UIResourceId test_id_
;
1322 TEST_F(UIResourceLostBeforeActivateTree
,
1323 RunMultiThread_DirectRenderer_ImplSidePaint
) {
1324 RunTest(true, false, true);
1327 TEST_F(UIResourceLostBeforeActivateTree
,
1328 RunMultiThread_DelegatingRenderer_ImplSidePaint
) {
1329 RunTest(true, true, true);
1332 // Resources evicted explicitly and by visibility changes.
1333 class UIResourceLostEviction
: public UIResourceLostTestSimple
{
1335 virtual void StepCompleteOnMainThread(int step
) OVERRIDE
{
1336 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1339 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1340 EXPECT_NE(0, ui_resource_
->id());
1341 PostSetNeedsCommitToMainThread();
1344 // Make the tree not visible.
1345 PostSetVisibleToMainThread(false);
1348 // Release resource before ending the test.
1349 ui_resource_
.reset();
1357 virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl
* impl
,
1358 bool visible
) OVERRIDE
{
1359 TestWebGraphicsContext3D
* context
= TestContext();
1361 // All resources should have been evicted.
1362 ASSERT_EQ(0u, context
->NumTextures());
1363 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1364 EXPECT_EQ(2, ui_resource_
->resource_create_count
);
1365 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1366 // Drawing is disabled both because of the evicted resources and
1367 // because the renderer is not visible.
1368 EXPECT_FALSE(impl
->CanDraw());
1369 // Make the renderer visible again.
1370 PostSetVisibleToMainThread(true);
1374 virtual void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1375 TestWebGraphicsContext3D
* context
= TestContext();
1376 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1377 switch (time_step_
) {
1379 // The resource should have been created on LTHI after the commit.
1380 ASSERT_EQ(1u, context
->NumTextures());
1381 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1382 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1383 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1384 EXPECT_TRUE(impl
->CanDraw());
1385 // Evict all UI resources. This will trigger a commit.
1386 impl
->EvictAllUIResources();
1387 ASSERT_EQ(0u, context
->NumTextures());
1388 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1389 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1390 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1391 EXPECT_FALSE(impl
->CanDraw());
1394 // The resource should have been recreated.
1395 ASSERT_EQ(1u, context
->NumTextures());
1396 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1397 EXPECT_EQ(2, ui_resource_
->resource_create_count
);
1398 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1399 EXPECT_TRUE(impl
->CanDraw());
1402 // The resource should have been recreated after visibility was
1404 ASSERT_EQ(1u, context
->NumTextures());
1405 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1406 EXPECT_EQ(3, ui_resource_
->resource_create_count
);
1407 EXPECT_EQ(2, ui_resource_
->lost_resource_count
);
1408 EXPECT_TRUE(impl
->CanDraw());
1414 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction
);
1416 class LayerTreeHostContextTestSurfaceCreateCallback
1417 : public LayerTreeHostContextTest
{
1419 LayerTreeHostContextTestSurfaceCreateCallback()
1420 : LayerTreeHostContextTest(),
1421 layer_(FakeContentLayer::Create(&client_
)) {}
1423 virtual void SetupTree() OVERRIDE
{
1424 layer_
->SetBounds(gfx::Size(10, 20));
1425 layer_tree_host()->SetRootLayer(layer_
);
1426 LayerTreeHostContextTest::SetupTree();
1429 virtual void BeginTest() OVERRIDE
{ PostSetNeedsCommitToMainThread(); }
1431 virtual void DidCommit() OVERRIDE
{
1432 switch (layer_tree_host()->source_frame_number()) {
1434 EXPECT_EQ(1u, layer_
->output_surface_created_count());
1435 layer_tree_host()->SetNeedsCommit();
1438 EXPECT_EQ(1u, layer_
->output_surface_created_count());
1439 layer_tree_host()->SetNeedsCommit();
1442 EXPECT_EQ(1u, layer_
->output_surface_created_count());
1445 EXPECT_EQ(2u, layer_
->output_surface_created_count());
1446 layer_tree_host()->SetNeedsCommit();
1451 virtual void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
1452 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1453 switch (LastCommittedSourceFrameNumber(impl
)) {
1467 virtual void AfterTest() OVERRIDE
{}
1470 FakeContentLayerClient client_
;
1471 scoped_refptr
<FakeContentLayer
> layer_
;
1474 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback
);
1476 class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
1477 : public LayerTreeHostContextTest
{
1479 virtual void BeginTest() OVERRIDE
{
1481 PostSetNeedsCommitToMainThread();
1484 virtual void ScheduledActionWillSendBeginMainFrame() OVERRIDE
{
1489 // Defer commits before the BeginFrame arrives, causing it to be delayed.
1490 MainThreadTaskRunner()->PostTask(
1492 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1493 DeferCommitsOnMainThread
,
1494 base::Unretained(this),
1496 // Meanwhile, lose the context while we are in defer commits.
1497 ImplThreadTaskRunner()->PostTask(
1499 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1500 LoseContextOnImplThread
,
1501 base::Unretained(this)));
1504 void LoseContextOnImplThread() {
1507 // After losing the context, stop deferring commits.
1508 MainThreadTaskRunner()->PostTask(
1510 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1511 DeferCommitsOnMainThread
,
1512 base::Unretained(this),
1516 void DeferCommitsOnMainThread(bool defer_commits
) {
1517 layer_tree_host()->SetDeferCommits(defer_commits
);
1520 virtual void WillBeginMainFrame() OVERRIDE
{
1521 // Don't begin a frame with a lost surface.
1522 EXPECT_FALSE(layer_tree_host()->output_surface_lost());
1525 virtual void DidCommitAndDrawFrame() OVERRIDE
{ EndTest(); }
1527 virtual void AfterTest() OVERRIDE
{}
1532 // TODO(danakj): We don't use scheduler with SingleThreadProxy yet.
1533 MULTI_THREAD_TEST_F(LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
);