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/failure_output_surface.h"
23 #include "cc/test/fake_content_layer.h"
24 #include "cc/test/fake_content_layer_client.h"
25 #include "cc/test/fake_content_layer_impl.h"
26 #include "cc/test/fake_delegated_renderer_layer.h"
27 #include "cc/test/fake_delegated_renderer_layer_impl.h"
28 #include "cc/test/fake_layer_tree_host_client.h"
29 #include "cc/test/fake_output_surface.h"
30 #include "cc/test/fake_output_surface_client.h"
31 #include "cc/test/fake_painted_scrollbar_layer.h"
32 #include "cc/test/fake_picture_layer.h"
33 #include "cc/test/fake_picture_layer_impl.h"
34 #include "cc/test/fake_scoped_ui_resource.h"
35 #include "cc/test/fake_scrollbar.h"
36 #include "cc/test/fake_video_frame_provider.h"
37 #include "cc/test/layer_tree_test.h"
38 #include "cc/test/render_pass_test_common.h"
39 #include "cc/test/test_context_provider.h"
40 #include "cc/test/test_shared_bitmap_manager.h"
41 #include "cc/test/test_web_graphics_context_3d.h"
42 #include "cc/trees/layer_tree_host_impl.h"
43 #include "cc/trees/layer_tree_impl.h"
44 #include "cc/trees/single_thread_proxy.h"
45 #include "gpu/GLES2/gl2extchromium.h"
46 #include "media/base/media.h"
48 using media::VideoFrame
;
53 // These tests deal with losing the 3d graphics context.
54 class LayerTreeHostContextTest
: public LayerTreeTest
{
56 LayerTreeHostContextTest()
59 times_to_fail_create_(0),
60 times_to_lose_during_commit_(0),
61 times_to_lose_during_draw_(0),
62 times_to_fail_recreate_(0),
63 times_to_expect_create_failed_(0),
64 times_create_failed_(0),
65 committed_at_least_once_(false),
66 context_should_support_io_surface_(false),
67 fallback_context_works_(false),
68 async_output_surface_creation_(false) {
69 media::InitializeMediaLibraryForTesting();
73 // For sanity-checking tests, they should only call this when the
74 // context is not lost.
76 context3d_
->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB
,
77 GL_INNOCENT_CONTEXT_RESET_ARB
);
81 virtual scoped_ptr
<TestWebGraphicsContext3D
> CreateContext3d() {
82 return TestWebGraphicsContext3D::Create();
85 scoped_ptr
<FakeOutputSurface
> CreateFakeOutputSurface() override
{
86 if (times_to_fail_create_
) {
87 --times_to_fail_create_
;
89 return make_scoped_ptr(new FailureOutputSurface(delegating_renderer()));
92 scoped_ptr
<TestWebGraphicsContext3D
> context3d
= CreateContext3d();
93 context3d_
= context3d
.get();
95 if (context_should_support_io_surface_
) {
96 context3d_
->set_have_extension_io_surface(true);
97 context3d_
->set_have_extension_egl_image(true);
100 if (delegating_renderer())
101 return FakeOutputSurface::CreateDelegating3d(context3d
.Pass());
103 return FakeOutputSurface::Create3d(context3d
.Pass());
106 DrawResult
PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
107 LayerTreeHostImpl::FrameData
* frame
,
108 DrawResult draw_result
) override
{
109 if (draw_result
== DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
) {
110 // Only valid for single-threaded impl-side painting, which activates
111 // immediately and will try to draw again when content has finished.
112 DCHECK(!host_impl
->proxy()->HasImplThread());
113 DCHECK(host_impl
->settings().impl_side_painting
);
116 EXPECT_EQ(DRAW_SUCCESS
, draw_result
);
117 if (!times_to_lose_during_draw_
)
120 --times_to_lose_during_draw_
;
123 times_to_fail_create_
= times_to_fail_recreate_
;
124 times_to_fail_recreate_
= 0;
129 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
130 committed_at_least_once_
= true;
132 if (!times_to_lose_during_commit_
)
134 --times_to_lose_during_commit_
;
137 times_to_fail_create_
= times_to_fail_recreate_
;
138 times_to_fail_recreate_
= 0;
141 void DidFailToInitializeOutputSurface() override
{ ++times_create_failed_
; }
143 void TearDown() override
{
144 LayerTreeTest::TearDown();
145 EXPECT_EQ(times_to_expect_create_failed_
, times_create_failed_
);
148 void ExpectCreateToFail() { ++times_to_expect_create_failed_
; }
151 TestWebGraphicsContext3D
* context3d_
;
152 int times_to_fail_create_
;
153 int times_to_lose_during_commit_
;
154 int times_to_lose_during_draw_
;
155 int times_to_fail_recreate_
;
156 int times_to_expect_create_failed_
;
157 int times_create_failed_
;
158 bool committed_at_least_once_
;
159 bool context_should_support_io_surface_
;
160 bool fallback_context_works_
;
161 bool async_output_surface_creation_
;
164 class LayerTreeHostContextTestLostContextSucceeds
165 : public LayerTreeHostContextTest
{
167 LayerTreeHostContextTestLostContextSucceeds()
168 : LayerTreeHostContextTest(),
171 num_losses_last_test_case_(-1),
172 recovered_context_(true),
173 first_initialized_(false) {}
175 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
177 void RequestNewOutputSurface() override
{
178 if (async_output_surface_creation_
) {
179 MainThreadTaskRunner()->PostTask(
180 FROM_HERE
, base::Bind(&LayerTreeHostContextTestLostContextSucceeds::
181 CreateAndSetOutputSurface
,
182 base::Unretained(this)));
184 CreateAndSetOutputSurface();
188 void CreateAndSetOutputSurface() {
189 scoped_ptr
<OutputSurface
> surface(
190 LayerTreeHostContextTest::CreateOutputSurface());
192 layer_tree_host()->SetOutputSurface(surface
.Pass());
195 void DidInitializeOutputSurface() override
{
196 if (first_initialized_
)
199 first_initialized_
= true;
201 recovered_context_
= true;
204 void AfterTest() override
{ EXPECT_EQ(11u, test_case_
); }
206 void DidCommitAndDrawFrame() override
{
207 // If the last frame had a context loss, then we'll commit again to
209 if (!recovered_context_
)
211 if (times_to_lose_during_commit_
)
213 if (times_to_lose_during_draw_
)
216 recovered_context_
= false;
218 InvalidateAndSetNeedsCommit();
223 virtual void InvalidateAndSetNeedsCommit() {
224 // Cause damage so we try to draw.
225 layer_tree_host()->root_layer()->SetNeedsDisplay();
226 layer_tree_host()->SetNeedsCommit();
229 bool NextTestCase() {
230 static const TestCase kTests
[] = {
231 // Losing the context and failing to recreate it (or losing it again
232 // immediately) a small number of times should succeed.
234 1, // times_to_lose_during_commit
235 0, // times_to_lose_during_draw
236 0, // times_to_fail_recreate
237 false, // fallback_context_works
238 false, // async_output_surface_creation
241 0, // times_to_lose_during_commit
242 1, // times_to_lose_during_draw
243 0, // times_to_fail_recreate
244 false, // fallback_context_works
245 false, // async_output_surface_creation
248 1, // times_to_lose_during_commit
249 0, // times_to_lose_during_draw
250 3, // times_to_fail_recreate
251 false, // fallback_context_works
252 false, // async_output_surface_creation
255 0, // times_to_lose_during_commit
256 1, // times_to_lose_during_draw
257 3, // times_to_fail_recreate
258 false, // fallback_context_works
259 false, // async_output_surface_creation
262 0, // times_to_lose_during_commit
263 1, // times_to_lose_during_draw
264 3, // times_to_fail_recreate
265 false, // fallback_context_works
266 true, // async_output_surface_creation
268 // Losing the context and recreating it any number of times should
271 10, // times_to_lose_during_commit
272 0, // times_to_lose_during_draw
273 0, // times_to_fail_recreate
274 false, // fallback_context_works
275 false, // async_output_surface_creation
278 0, // times_to_lose_during_commit
279 10, // times_to_lose_during_draw
280 0, // times_to_fail_recreate
281 false, // fallback_context_works
282 false, // async_output_surface_creation
285 10, // times_to_lose_during_commit
286 0, // times_to_lose_during_draw
287 0, // times_to_fail_recreate
288 false, // fallback_context_works
289 true, // async_output_surface_creation
292 0, // times_to_lose_during_commit
293 10, // times_to_lose_during_draw
294 0, // times_to_fail_recreate
295 false, // fallback_context_works
296 true, // async_output_surface_creation
298 // Losing the context, failing to reinitialize it, and making a fallback
299 // context should work.
301 0, // times_to_lose_during_commit
302 1, // times_to_lose_during_draw
303 0, // times_to_fail_recreate
304 true, // fallback_context_works
305 false, // async_output_surface_creation
308 0, // times_to_lose_during_commit
309 1, // times_to_lose_during_draw
310 0, // times_to_fail_recreate
311 true, // fallback_context_works
312 true, // async_output_surface_creation
316 if (test_case_
>= arraysize(kTests
))
318 // Make sure that we lost our context at least once in the last test run so
319 // the test did something.
320 EXPECT_GT(num_losses_
, num_losses_last_test_case_
);
321 num_losses_last_test_case_
= num_losses_
;
323 times_to_lose_during_commit_
=
324 kTests
[test_case_
].times_to_lose_during_commit
;
325 times_to_lose_during_draw_
= kTests
[test_case_
].times_to_lose_during_draw
;
326 times_to_fail_recreate_
= kTests
[test_case_
].times_to_fail_recreate
;
327 fallback_context_works_
= kTests
[test_case_
].fallback_context_works
;
328 async_output_surface_creation_
=
329 kTests
[test_case_
].async_output_surface_creation
;
335 int times_to_lose_during_commit
;
336 int times_to_lose_during_draw
;
337 int times_to_fail_recreate
;
338 bool fallback_context_works
;
339 bool async_output_surface_creation
;
345 int num_losses_last_test_case_
;
346 bool recovered_context_
;
347 bool first_initialized_
;
350 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds
);
352 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
353 : public LayerTreeHostContextTest
{
355 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
356 : LayerTreeHostContextTest() {}
358 void WillBeginTest() override
{
359 // Override and do not signal SetLayerTreeHostClientReady.
362 void BeginTest() override
{
363 PostSetNeedsCommitToMainThread();
367 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
372 void DidInitializeOutputSurface() override
{ EXPECT_TRUE(false); }
374 void AfterTest() override
{}
377 SINGLE_AND_MULTI_THREAD_TEST_F(
378 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
);
380 class MultipleCompositeDoesNotCreateOutputSurface
381 : public LayerTreeHostContextTest
{
383 MultipleCompositeDoesNotCreateOutputSurface()
384 : LayerTreeHostContextTest(), request_count_(0) {}
386 void InitializeSettings(LayerTreeSettings
* settings
) override
{
387 settings
->single_thread_proxy_scheduler
= false;
390 void RequestNewOutputSurface() override
{
391 EXPECT_GE(1, ++request_count_
);
395 void BeginTest() override
{
396 layer_tree_host()->Composite(base::TimeTicks());
397 layer_tree_host()->Composite(base::TimeTicks());
400 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
405 void DidInitializeOutputSurface() override
{ EXPECT_TRUE(false); }
407 void AfterTest() override
{}
412 SINGLE_THREAD_NOIMPL_TEST_F(MultipleCompositeDoesNotCreateOutputSurface
);
414 // This test makes sure that once a SingleThreadProxy issues a
415 // DidFailToInitializeOutputSurface, that future Composite calls will not
416 // trigger additional requests for output surfaces.
417 class FailedCreateDoesNotCreateExtraOutputSurface
418 : public LayerTreeHostContextTest
{
420 FailedCreateDoesNotCreateExtraOutputSurface()
421 : LayerTreeHostContextTest(), num_requests_(0), has_failed_(false) {}
423 void InitializeSettings(LayerTreeSettings
* settings
) override
{
424 settings
->single_thread_proxy_scheduler
= false;
427 void RequestNewOutputSurface() override
{
429 // There should be one initial request and then one request from
430 // the LayerTreeTest test hooks DidFailToInitializeOutputSurface (which is
431 // hard to skip). This second request is just ignored and is test cruft.
432 EXPECT_LE(num_requests_
, 2);
433 if (num_requests_
> 1)
435 ExpectCreateToFail();
436 layer_tree_host()->SetOutputSurface(
437 make_scoped_ptr(new FailureOutputSurface(false)));
440 void BeginTest() override
{
441 // First composite tries to create a surface.
442 layer_tree_host()->Composite(base::TimeTicks());
443 EXPECT_EQ(num_requests_
, 2);
444 EXPECT_TRUE(has_failed_
);
446 // Second composite should not request or fail.
447 layer_tree_host()->Composite(base::TimeTicks());
448 EXPECT_EQ(num_requests_
, 2);
452 void DidInitializeOutputSurface() override
{ EXPECT_TRUE(false); }
454 void DidFailToInitializeOutputSurface() override
{
455 LayerTreeHostContextTest::DidFailToInitializeOutputSurface();
456 EXPECT_FALSE(has_failed_
);
460 void AfterTest() override
{}
466 SINGLE_THREAD_NOIMPL_TEST_F(FailedCreateDoesNotCreateExtraOutputSurface
);
468 class LayerTreeHostContextTestCommitAfterDelayedOutputSurface
469 : public LayerTreeHostContextTest
{
471 LayerTreeHostContextTestCommitAfterDelayedOutputSurface()
472 : LayerTreeHostContextTest(), creating_output_(false) {}
474 void InitializeSettings(LayerTreeSettings
* settings
) override
{
475 settings
->single_thread_proxy_scheduler
= false;
478 void RequestNewOutputSurface() override
{
479 MainThreadTaskRunner()->PostTask(
481 base::Bind(&LayerTreeHostContextTestCommitAfterDelayedOutputSurface::
482 CreateAndSetOutputSurface
,
483 base::Unretained(this)));
486 void CreateAndSetOutputSurface() {
487 creating_output_
= true;
488 layer_tree_host()->SetOutputSurface(
489 LayerTreeHostContextTest::CreateOutputSurface());
492 void BeginTest() override
{ layer_tree_host()->Composite(base::TimeTicks()); }
494 void ScheduleComposite() override
{
495 if (creating_output_
)
499 void AfterTest() override
{}
501 bool creating_output_
;
504 SINGLE_THREAD_NOIMPL_TEST_F(
505 LayerTreeHostContextTestCommitAfterDelayedOutputSurface
);
507 class LayerTreeHostContextTestAvoidUnnecessaryComposite
508 : public LayerTreeHostContextTest
{
510 LayerTreeHostContextTestAvoidUnnecessaryComposite()
511 : LayerTreeHostContextTest(), in_composite_(false) {}
513 void InitializeSettings(LayerTreeSettings
* settings
) override
{
514 settings
->single_thread_proxy_scheduler
= false;
517 void RequestNewOutputSurface() override
{
518 layer_tree_host()->SetOutputSurface(
519 LayerTreeHostContextTest::CreateOutputSurface());
523 void BeginTest() override
{
524 in_composite_
= true;
525 layer_tree_host()->Composite(base::TimeTicks());
526 in_composite_
= false;
529 void ScheduleComposite() override
{ EXPECT_FALSE(in_composite_
); }
531 void AfterTest() override
{}
536 SINGLE_THREAD_NOIMPL_TEST_F(LayerTreeHostContextTestAvoidUnnecessaryComposite
);
538 class LayerTreeHostContextTestLostContextSucceedsWithContent
539 : public LayerTreeHostContextTestLostContextSucceeds
{
541 void SetupTree() override
{
542 root_
= Layer::Create();
543 root_
->SetBounds(gfx::Size(10, 10));
544 root_
->SetIsDrawable(true);
546 // Paint non-solid color.
548 paint
.setColor(SkColorSetARGB(100, 80, 200, 200));
549 client_
.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint
);
551 if (layer_tree_host()->settings().impl_side_painting
)
552 layer_
= FakePictureLayer::Create(&client_
);
554 layer_
= FakeContentLayer::Create(&client_
);
555 layer_
->SetBounds(gfx::Size(10, 10));
556 layer_
->SetIsDrawable(true);
558 root_
->AddChild(layer_
);
560 layer_tree_host()->SetRootLayer(root_
);
561 LayerTreeHostContextTest::SetupTree();
564 void InvalidateAndSetNeedsCommit() override
{
565 // Invalidate the render surface so we don't try to use a cached copy of the
566 // surface. We want to make sure to test the drawing paths for drawing to
568 layer_
->SetNeedsDisplay();
569 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
572 void DrawLayersOnThread(LayerTreeHostImpl
* host_impl
) override
{
573 if (!host_impl
->settings().impl_side_painting
) {
574 FakeContentLayerImpl
* content_impl
= static_cast<FakeContentLayerImpl
*>(
575 host_impl
->active_tree()->root_layer()->children()[0]);
576 // Even though the context was lost, we should have a resource. The
577 // TestWebGraphicsContext3D ensures that this resource is created with
578 // the active context.
579 EXPECT_TRUE(content_impl
->HaveResourceForTileAt(0, 0));
581 FakePictureLayerImpl
* picture_impl
= static_cast<FakePictureLayerImpl
*>(
582 host_impl
->active_tree()->root_layer()->children()[0]);
583 EXPECT_TRUE(picture_impl
->HighResTiling()->TileAt(0, 0)->IsReadyToDraw());
588 FakeContentLayerClient client_
;
589 scoped_refptr
<Layer
> root_
;
590 scoped_refptr
<Layer
> layer_
;
593 // This test uses TiledLayer and PictureLayer to check for a working context.
594 SINGLE_AND_MULTI_THREAD_TEST_F(
595 LayerTreeHostContextTestLostContextSucceedsWithContent
);
597 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
598 : public LayerTreeHostContextTest
{
600 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
601 : times_to_fail_(1), times_initialized_(0) {
602 times_to_fail_create_
= times_to_fail_
;
605 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
607 void DidInitializeOutputSurface() override
{ times_initialized_
++; }
609 void DrawLayersOnThread(LayerTreeHostImpl
* host_impl
) override
{ EndTest(); }
611 void AfterTest() override
{
612 EXPECT_EQ(times_to_fail_
, times_create_failed_
);
613 EXPECT_NE(0, times_initialized_
);
618 int times_initialized_
;
621 SINGLE_AND_MULTI_THREAD_TEST_F(
622 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
);
624 class LayerTreeHostContextTestLostContextAndEvictTextures
625 : public LayerTreeHostContextTest
{
627 LayerTreeHostContextTestLostContextAndEvictTextures()
628 : LayerTreeHostContextTest(),
631 lost_context_(false) {}
633 void SetupTree() override
{
634 // Paint non-solid color.
636 paint
.setColor(SkColorSetARGB(100, 80, 200, 200));
637 client_
.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint
);
639 if (layer_tree_host()->settings().impl_side_painting
) {
640 picture_layer_
= FakePictureLayer::Create(&client_
);
641 picture_layer_
->SetBounds(gfx::Size(10, 20));
642 layer_tree_host()->SetRootLayer(picture_layer_
);
644 content_layer_
= FakeContentLayer::Create(&client_
);
645 content_layer_
->SetBounds(gfx::Size(10, 20));
646 layer_tree_host()->SetRootLayer(content_layer_
);
649 LayerTreeHostContextTest::SetupTree();
652 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
654 void PostEvictTextures() {
655 if (HasImplThread()) {
656 ImplThreadTaskRunner()->PostTask(
658 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
659 EvictTexturesOnImplThread
,
660 base::Unretained(this)));
662 DebugScopedSetImplThread
impl(proxy());
663 EvictTexturesOnImplThread();
667 void EvictTexturesOnImplThread() {
668 impl_host_
->EvictTexturesForTesting();
670 if (lose_after_evict_
) {
672 lost_context_
= true;
676 void DidCommitAndDrawFrame() override
{
677 if (num_commits_
> 1)
679 if (!layer_tree_host()->settings().impl_side_painting
) {
680 EXPECT_TRUE(content_layer_
->HaveBackingAt(0, 0));
685 void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) override
{
686 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
687 if (num_commits_
> 1)
690 if (!lose_after_evict_
) {
692 lost_context_
= true;
696 void DrawLayersOnThread(LayerTreeHostImpl
* impl
) override
{
697 if (impl
->settings().impl_side_painting
) {
698 FakePictureLayerImpl
* picture_impl
=
699 static_cast<FakePictureLayerImpl
*>(impl
->active_tree()->root_layer());
700 EXPECT_TRUE(picture_impl
->HighResTiling()->TileAt(0, 0)->IsReadyToDraw());
702 FakeContentLayerImpl
* content_impl
=
703 static_cast<FakeContentLayerImpl
*>(impl
->active_tree()->root_layer());
704 EXPECT_TRUE(content_impl
->HaveResourceForTileAt(0, 0));
712 void DidInitializeOutputSurface() override
{}
714 void AfterTest() override
{}
717 bool lose_after_evict_
;
718 FakeContentLayerClient client_
;
719 scoped_refptr
<FakeContentLayer
> content_layer_
;
720 scoped_refptr
<FakePictureLayer
> picture_layer_
;
721 LayerTreeHostImpl
* impl_host_
;
726 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
727 LoseAfterEvict_SingleThread_DirectRenderer
) {
728 lose_after_evict_
= true;
729 RunTest(false, false, false);
732 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
733 LoseAfterEvict_SingleThread_DelegatingRenderer
) {
734 lose_after_evict_
= true;
735 RunTest(false, true, false);
738 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
739 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint
) {
740 lose_after_evict_
= true;
741 RunTest(true, false, false);
744 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
745 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint
) {
746 lose_after_evict_
= true;
747 RunTest(true, true, false);
750 // Flaky on all platforms, http://crbug.com/310979
751 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
752 DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint
) {
753 lose_after_evict_
= true;
754 RunTest(true, true, true);
757 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
758 LoseBeforeEvict_SingleThread_DirectRenderer
) {
759 lose_after_evict_
= false;
760 RunTest(false, false, false);
763 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
764 LoseBeforeEvict_SingleThread_DelegatingRenderer
) {
765 lose_after_evict_
= false;
766 RunTest(false, true, false);
769 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
770 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint
) {
771 lose_after_evict_
= false;
772 RunTest(true, false, false);
775 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
776 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint
) {
777 lose_after_evict_
= false;
778 RunTest(true, false, true);
781 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
782 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint
) {
783 lose_after_evict_
= false;
784 RunTest(true, true, false);
787 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures
,
788 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint
) {
789 lose_after_evict_
= false;
790 RunTest(true, true, true);
793 class LayerTreeHostContextTestLostContextWhileUpdatingResources
794 : public LayerTreeHostContextTest
{
796 LayerTreeHostContextTestLostContextWhileUpdatingResources()
797 : num_children_(50), times_to_lose_on_end_query_(3) {}
799 scoped_ptr
<TestWebGraphicsContext3D
> CreateContext3d() override
{
800 scoped_ptr
<TestWebGraphicsContext3D
> context
=
801 LayerTreeHostContextTest::CreateContext3d();
802 if (times_to_lose_on_end_query_
) {
803 --times_to_lose_on_end_query_
;
804 context
->set_times_end_query_succeeds(5);
806 return context
.Pass();
809 void SetupTree() override
{
810 if (layer_tree_host()->settings().impl_side_painting
)
811 parent_
= FakePictureLayer::Create(&client_
);
813 parent_
= FakeContentLayer::Create(&client_
);
815 parent_
->SetBounds(gfx::Size(num_children_
, 1));
817 for (int i
= 0; i
< num_children_
; i
++) {
818 scoped_refptr
<Layer
> child
;
819 if (layer_tree_host()->settings().impl_side_painting
)
820 child
= FakePictureLayer::Create(&client_
);
822 child
= FakeContentLayer::Create(&client_
);
823 child
->SetPosition(gfx::PointF(i
, 0.f
));
824 child
->SetBounds(gfx::Size(1, 1));
825 parent_
->AddChild(child
);
828 layer_tree_host()->SetRootLayer(parent_
);
829 LayerTreeHostContextTest::SetupTree();
832 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
834 void DrawLayersOnThread(LayerTreeHostImpl
* host_impl
) override
{
835 EXPECT_EQ(0, times_to_lose_on_end_query_
);
839 void AfterTest() override
{ EXPECT_EQ(0, times_to_lose_on_end_query_
); }
842 FakeContentLayerClient client_
;
843 scoped_refptr
<Layer
> parent_
;
845 int times_to_lose_on_end_query_
;
848 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
849 LayerTreeHostContextTestLostContextWhileUpdatingResources
);
851 class LayerTreeHostContextTestLayersNotified
: public LayerTreeHostContextTest
{
853 LayerTreeHostContextTestLayersNotified()
854 : LayerTreeHostContextTest(), num_commits_(0) {}
856 void SetupTree() override
{
857 if (layer_tree_host()->settings().impl_side_painting
) {
858 root_
= FakePictureLayer::Create(&client_
);
859 child_
= FakePictureLayer::Create(&client_
);
860 grandchild_
= FakePictureLayer::Create(&client_
);
862 root_
= FakeContentLayer::Create(&client_
);
863 child_
= FakeContentLayer::Create(&client_
);
864 grandchild_
= FakeContentLayer::Create(&client_
);
867 root_
->AddChild(child_
);
868 child_
->AddChild(grandchild_
);
870 layer_tree_host()->SetRootLayer(root_
);
871 LayerTreeHostContextTest::SetupTree();
874 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
876 void DidActivateTreeOnThread(LayerTreeHostImpl
* host_impl
) override
{
877 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl
);
879 FakePictureLayerImpl
* root_picture
= NULL
;
880 FakePictureLayerImpl
* child_picture
= NULL
;
881 FakePictureLayerImpl
* grandchild_picture
= NULL
;
882 FakeContentLayerImpl
* root_content
= NULL
;
883 FakeContentLayerImpl
* child_content
= NULL
;
884 FakeContentLayerImpl
* grandchild_content
= NULL
;
886 if (host_impl
->settings().impl_side_painting
) {
887 root_picture
= static_cast<FakePictureLayerImpl
*>(
888 host_impl
->active_tree()->root_layer());
890 static_cast<FakePictureLayerImpl
*>(root_picture
->children()[0]);
892 static_cast<FakePictureLayerImpl
*>(child_picture
->children()[0]);
895 root_content
= static_cast<FakeContentLayerImpl
*>(
896 host_impl
->active_tree()->root_layer());
898 static_cast<FakeContentLayerImpl
*>(root_content
->children()[0]);
900 static_cast<FakeContentLayerImpl
*>(child_content
->children()[0]);
904 switch (num_commits_
) {
906 if (host_impl
->settings().impl_side_painting
) {
907 EXPECT_EQ(0u, root_picture
->release_resources_count());
908 EXPECT_EQ(0u, child_picture
->release_resources_count());
909 EXPECT_EQ(0u, grandchild_picture
->release_resources_count());
911 EXPECT_EQ(0u, root_content
->lost_output_surface_count());
912 EXPECT_EQ(0u, child_content
->lost_output_surface_count());
913 EXPECT_EQ(0u, grandchild_content
->lost_output_surface_count());
916 // Lose the context and struggle to recreate it.
918 times_to_fail_create_
= 1;
921 if (host_impl
->settings().impl_side_painting
) {
922 EXPECT_TRUE(root_picture
->release_resources_count());
923 EXPECT_TRUE(child_picture
->release_resources_count());
924 EXPECT_TRUE(grandchild_picture
->release_resources_count());
926 EXPECT_TRUE(root_content
->lost_output_surface_count());
927 EXPECT_TRUE(child_content
->lost_output_surface_count());
928 EXPECT_TRUE(grandchild_content
->lost_output_surface_count());
938 void AfterTest() override
{}
943 FakeContentLayerClient client_
;
944 scoped_refptr
<Layer
> root_
;
945 scoped_refptr
<Layer
> child_
;
946 scoped_refptr
<Layer
> grandchild_
;
949 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified
);
951 class LayerTreeHostContextTestDontUseLostResources
952 : public LayerTreeHostContextTest
{
954 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
955 context_should_support_io_surface_
= true;
957 child_output_surface_
= FakeOutputSurface::Create3d();
958 child_output_surface_
->BindToClient(&output_surface_client_
);
959 shared_bitmap_manager_
.reset(new TestSharedBitmapManager());
960 child_resource_provider_
=
961 ResourceProvider::Create(child_output_surface_
.get(),
962 shared_bitmap_manager_
.get(),
970 static void EmptyReleaseCallback(unsigned sync_point
, bool lost
) {}
972 void SetupTree() override
{
973 gpu::gles2::GLES2Interface
* gl
=
974 child_output_surface_
->context_provider()->ContextGL();
976 scoped_ptr
<DelegatedFrameData
> frame_data(new DelegatedFrameData
);
978 scoped_ptr
<TestRenderPass
> pass_for_quad
= TestRenderPass::Create();
979 pass_for_quad
->SetNew(
980 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
982 gfx::Rect(0, 0, 10, 10),
983 gfx::Rect(0, 0, 10, 10),
986 scoped_ptr
<TestRenderPass
> pass
= TestRenderPass::Create();
987 pass
->SetNew(RenderPassId(1, 1),
988 gfx::Rect(0, 0, 10, 10),
989 gfx::Rect(0, 0, 10, 10),
991 pass
->AppendOneOfEveryQuadType(child_resource_provider_
.get(),
994 frame_data
->render_pass_list
.push_back(pass_for_quad
.Pass());
995 frame_data
->render_pass_list
.push_back(pass
.Pass());
997 delegated_resource_collection_
= new DelegatedFrameResourceCollection
;
998 delegated_frame_provider_
= new DelegatedFrameProvider(
999 delegated_resource_collection_
.get(), frame_data
.Pass());
1001 ResourceProvider::ResourceId resource
=
1002 child_resource_provider_
->CreateResource(
1003 gfx::Size(4, 4), GL_CLAMP_TO_EDGE
,
1004 ResourceProvider::TEXTURE_HINT_IMMUTABLE
, RGBA_8888
);
1005 ResourceProvider::ScopedWriteLockGL
lock(child_resource_provider_
.get(),
1008 gpu::Mailbox mailbox
;
1009 gl
->GenMailboxCHROMIUM(mailbox
.name
);
1010 GLuint sync_point
= gl
->InsertSyncPointCHROMIUM();
1012 scoped_refptr
<Layer
> root
= Layer::Create();
1013 root
->SetBounds(gfx::Size(10, 10));
1014 root
->SetIsDrawable(true);
1016 scoped_refptr
<FakeDelegatedRendererLayer
> delegated
=
1017 FakeDelegatedRendererLayer::Create(delegated_frame_provider_
.get());
1018 delegated
->SetBounds(gfx::Size(10, 10));
1019 delegated
->SetIsDrawable(true);
1020 root
->AddChild(delegated
);
1022 scoped_refptr
<Layer
> layer
;
1023 if (layer_tree_host()->settings().impl_side_painting
)
1024 layer
= PictureLayer::Create(&client_
);
1026 layer
= ContentLayer::Create(&client_
);
1027 layer
->SetBounds(gfx::Size(10, 10));
1028 layer
->SetIsDrawable(true);
1029 root
->AddChild(layer
);
1031 scoped_refptr
<TextureLayer
> texture
= TextureLayer::CreateForMailbox(NULL
);
1032 texture
->SetBounds(gfx::Size(10, 10));
1033 texture
->SetIsDrawable(true);
1034 texture
->SetTextureMailbox(
1035 TextureMailbox(mailbox
, GL_TEXTURE_2D
, sync_point
),
1036 SingleReleaseCallback::Create(
1037 base::Bind(&LayerTreeHostContextTestDontUseLostResources::
1038 EmptyReleaseCallback
)));
1039 root
->AddChild(texture
);
1041 scoped_refptr
<Layer
> mask
;
1042 if (layer_tree_host()->settings().impl_side_painting
)
1043 mask
= PictureLayer::Create(&client_
);
1045 mask
= ContentLayer::Create(&client_
);
1046 mask
->SetBounds(gfx::Size(10, 10));
1048 scoped_refptr
<Layer
> layer_with_mask
;
1049 if (layer_tree_host()->settings().impl_side_painting
)
1050 layer_with_mask
= PictureLayer::Create(&client_
);
1052 layer_with_mask
= ContentLayer::Create(&client_
);
1053 layer_with_mask
->SetBounds(gfx::Size(10, 10));
1054 layer_with_mask
->SetIsDrawable(true);
1055 layer_with_mask
->SetMaskLayer(mask
.get());
1056 root
->AddChild(layer_with_mask
);
1058 scoped_refptr
<VideoLayer
> video_color
=
1059 VideoLayer::Create(&color_frame_provider_
, media::VIDEO_ROTATION_0
);
1060 video_color
->SetBounds(gfx::Size(10, 10));
1061 video_color
->SetIsDrawable(true);
1062 root
->AddChild(video_color
);
1064 scoped_refptr
<VideoLayer
> video_hw
=
1065 VideoLayer::Create(&hw_frame_provider_
, media::VIDEO_ROTATION_0
);
1066 video_hw
->SetBounds(gfx::Size(10, 10));
1067 video_hw
->SetIsDrawable(true);
1068 root
->AddChild(video_hw
);
1070 scoped_refptr
<VideoLayer
> video_scaled_hw
=
1071 VideoLayer::Create(&scaled_hw_frame_provider_
, media::VIDEO_ROTATION_0
);
1072 video_scaled_hw
->SetBounds(gfx::Size(10, 10));
1073 video_scaled_hw
->SetIsDrawable(true);
1074 root
->AddChild(video_scaled_hw
);
1076 color_video_frame_
= VideoFrame::CreateColorFrame(
1077 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
1078 hw_video_frame_
= VideoFrame::WrapNativeTexture(
1079 gpu::MailboxHolder(mailbox
, GL_TEXTURE_2D
, sync_point
),
1080 media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
1081 gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta(), false);
1082 scaled_hw_video_frame_
= VideoFrame::WrapNativeTexture(
1083 gpu::MailboxHolder(mailbox
, GL_TEXTURE_2D
, sync_point
),
1084 media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
1085 gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta(), false);
1087 color_frame_provider_
.set_frame(color_video_frame_
);
1088 hw_frame_provider_
.set_frame(hw_video_frame_
);
1089 scaled_hw_frame_provider_
.set_frame(scaled_hw_video_frame_
);
1091 if (!delegating_renderer()) {
1092 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
1093 scoped_refptr
<IOSurfaceLayer
> io_surface
= IOSurfaceLayer::Create();
1094 io_surface
->SetBounds(gfx::Size(10, 10));
1095 io_surface
->SetIsDrawable(true);
1096 io_surface
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
1097 root
->AddChild(io_surface
);
1101 LayerTreeDebugState debug_state
;
1102 debug_state
.show_property_changed_rects
= true;
1103 layer_tree_host()->SetDebugState(debug_state
);
1105 scoped_refptr
<PaintedScrollbarLayer
> scrollbar
=
1106 PaintedScrollbarLayer::Create(
1107 scoped_ptr
<Scrollbar
>(new FakeScrollbar
).Pass(), layer
->id());
1108 scrollbar
->SetBounds(gfx::Size(10, 10));
1109 scrollbar
->SetIsDrawable(true);
1110 root
->AddChild(scrollbar
);
1112 layer_tree_host()->SetRootLayer(root
);
1113 LayerTreeHostContextTest::SetupTree();
1116 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1118 void CommitCompleteOnThread(LayerTreeHostImpl
* host_impl
) override
{
1119 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl
);
1121 if (host_impl
->active_tree()->source_frame_number() == 3) {
1122 // On the third commit we're recovering from context loss. Hardware
1123 // video frames should not be reused by the VideoFrameProvider, but
1124 // software frames can be.
1125 hw_frame_provider_
.set_frame(NULL
);
1126 scaled_hw_frame_provider_
.set_frame(NULL
);
1130 DrawResult
PrepareToDrawOnThread(LayerTreeHostImpl
* host_impl
,
1131 LayerTreeHostImpl::FrameData
* frame
,
1132 DrawResult draw_result
) override
{
1133 if (host_impl
->active_tree()->source_frame_number() == 2) {
1134 // Lose the context during draw on the second commit. This will cause
1135 // a third commit to recover.
1136 context3d_
->set_times_bind_texture_succeeds(0);
1141 scoped_ptr
<FakeOutputSurface
> CreateFakeOutputSurface() override
{
1142 // This will get called twice:
1143 // First when we create the initial output surface...
1144 if (layer_tree_host()->source_frame_number() > 0) {
1145 // ... and then again after we forced the context to be lost.
1146 lost_context_
= true;
1148 return LayerTreeHostContextTest::CreateFakeOutputSurface();
1151 void DidCommitAndDrawFrame() override
{
1152 ASSERT_TRUE(layer_tree_host()->hud_layer());
1153 // End the test once we know the 3nd frame drew.
1154 if (layer_tree_host()->source_frame_number() < 5) {
1155 layer_tree_host()->root_layer()->SetNeedsDisplay();
1156 layer_tree_host()->SetNeedsCommit();
1162 void AfterTest() override
{ EXPECT_TRUE(lost_context_
); }
1165 FakeContentLayerClient client_
;
1168 FakeOutputSurfaceClient output_surface_client_
;
1169 scoped_ptr
<FakeOutputSurface
> child_output_surface_
;
1170 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager_
;
1171 scoped_ptr
<ResourceProvider
> child_resource_provider_
;
1173 scoped_refptr
<DelegatedFrameResourceCollection
>
1174 delegated_resource_collection_
;
1175 scoped_refptr
<DelegatedFrameProvider
> delegated_frame_provider_
;
1177 scoped_refptr
<VideoFrame
> color_video_frame_
;
1178 scoped_refptr
<VideoFrame
> hw_video_frame_
;
1179 scoped_refptr
<VideoFrame
> scaled_hw_video_frame_
;
1181 FakeVideoFrameProvider color_frame_provider_
;
1182 FakeVideoFrameProvider hw_frame_provider_
;
1183 FakeVideoFrameProvider scaled_hw_frame_provider_
;
1186 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources
);
1188 class ImplSidePaintingLayerTreeHostContextTest
1189 : public LayerTreeHostContextTest
{
1191 void InitializeSettings(LayerTreeSettings
* settings
) override
{
1192 settings
->impl_side_painting
= true;
1196 class LayerTreeHostContextTestImplSidePainting
1197 : public ImplSidePaintingLayerTreeHostContextTest
{
1199 void SetupTree() override
{
1200 scoped_refptr
<Layer
> root
= Layer::Create();
1201 root
->SetBounds(gfx::Size(10, 10));
1202 root
->SetIsDrawable(true);
1204 scoped_refptr
<PictureLayer
> picture
= PictureLayer::Create(&client_
);
1205 picture
->SetBounds(gfx::Size(10, 10));
1206 picture
->SetIsDrawable(true);
1207 root
->AddChild(picture
);
1209 layer_tree_host()->SetRootLayer(root
);
1210 LayerTreeHostContextTest::SetupTree();
1213 void BeginTest() override
{
1214 times_to_lose_during_commit_
= 1;
1215 PostSetNeedsCommitToMainThread();
1218 void AfterTest() override
{}
1220 void DidInitializeOutputSurface() override
{ EndTest(); }
1223 FakeContentLayerClient client_
;
1226 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting
);
1228 class ScrollbarLayerLostContext
: public LayerTreeHostContextTest
{
1230 ScrollbarLayerLostContext() : commits_(0) {}
1232 void BeginTest() override
{
1233 scoped_refptr
<Layer
> scroll_layer
= Layer::Create();
1235 FakePaintedScrollbarLayer::Create(false, true, scroll_layer
->id());
1236 scrollbar_layer_
->SetBounds(gfx::Size(10, 100));
1237 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_
);
1238 layer_tree_host()->root_layer()->AddChild(scroll_layer
);
1239 PostSetNeedsCommitToMainThread();
1242 void AfterTest() override
{}
1244 void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) override
{
1245 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1250 // First (regular) update, we should upload 2 resources (thumb, and
1252 EXPECT_EQ(1, scrollbar_layer_
->update_count());
1256 // Second update, after the lost context, we should still upload 2
1257 // resources even if the contents haven't changed.
1258 EXPECT_EQ(2, scrollbar_layer_
->update_count());
1268 scoped_refptr
<FakePaintedScrollbarLayer
> scrollbar_layer_
;
1271 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext
);
1273 class UIResourceLostTest
: public LayerTreeHostContextTest
{
1275 UIResourceLostTest() : time_step_(0) {}
1276 void InitializeSettings(LayerTreeSettings
* settings
) override
{
1277 settings
->renderer_settings
.texture_id_allocation_chunk_size
= 1;
1279 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1280 void AfterTest() override
{}
1282 // This is called on the main thread after each commit and
1283 // DidActivateTreeOnThread, with the value of time_step_ at the time
1284 // of the call to DidActivateTreeOnThread. Similar tests will do
1285 // work on the main thread in DidCommit but that is unsuitable because
1286 // the main thread work for these tests must happen after
1287 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1289 virtual void StepCompleteOnMainThread(int time_step
) = 0;
1291 // Called after DidActivateTreeOnThread. If this is done during the commit,
1292 // the call to StepCompleteOnMainThread will not occur until after
1293 // the commit completes, because the main thread is blocked.
1294 void PostStepCompleteToMainThread() {
1295 proxy()->MainThreadTaskRunner()->PostTask(
1297 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal
,
1298 base::Unretained(this),
1302 void PostLoseContextToImplThread() {
1303 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1304 ImplThreadTaskRunner()->PostTask(
1306 base::Bind(&LayerTreeHostContextTest::LoseContext
,
1307 base::Unretained(this)));
1312 scoped_ptr
<FakeScopedUIResource
> ui_resource_
;
1315 void StepCompleteOnMainThreadInternal(int step
) {
1316 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1317 StepCompleteOnMainThread(step
);
1321 class UIResourceLostTestSimple
: public UIResourceLostTest
{
1323 // This is called when the commit is complete and the new layer tree has been
1325 virtual void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) = 0;
1327 void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) override
{
1328 if (!impl
->settings().impl_side_painting
) {
1329 StepCompleteOnImplThread(impl
);
1330 PostStepCompleteToMainThread();
1335 void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
1336 if (impl
->settings().impl_side_painting
) {
1337 StepCompleteOnImplThread(impl
);
1338 PostStepCompleteToMainThread();
1344 // Losing context after an UI resource has been created.
1345 class UIResourceLostAfterCommit
: public UIResourceLostTestSimple
{
1347 void StepCompleteOnMainThread(int step
) override
{
1348 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1351 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1352 // Expects a valid UIResourceId.
1353 EXPECT_NE(0, ui_resource_
->id());
1354 PostSetNeedsCommitToMainThread();
1357 // Release resource before ending the test.
1358 ui_resource_
= nullptr;
1367 void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) override
{
1368 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1369 switch (time_step_
) {
1371 // The resource should have been created on LTHI after the commit.
1372 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1373 PostSetNeedsCommitToMainThread();
1379 // The resources should have been recreated. The bitmap callback should
1380 // have been called once with the resource_lost flag set to true.
1381 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1382 // Resource Id on the impl-side have been recreated as well. Note
1383 // that the same UIResourceId persists after the context lost.
1384 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1385 PostSetNeedsCommitToMainThread();
1391 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit
);
1393 // Losing context before UI resource requests can be commited. Three sequences
1394 // of creation/deletion are considered:
1395 // 1. Create one resource -> Context Lost => Expect the resource to have been
1397 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1398 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1399 // test_id1_ to have been created.
1400 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1401 // the resource to not exist in the manager.
1402 class UIResourceLostBeforeCommit
: public UIResourceLostTestSimple
{
1404 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1406 void StepCompleteOnMainThread(int step
) override
{
1409 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1410 // Lose the context on the impl thread before the commit.
1411 PostLoseContextToImplThread();
1415 // Currently one resource has been created.
1416 test_id0_
= ui_resource_
->id();
1417 // Delete this resource.
1418 ui_resource_
= nullptr;
1419 // Create another resource.
1420 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1421 test_id1_
= ui_resource_
->id();
1422 // Sanity check that two resource creations return different ids.
1423 EXPECT_NE(test_id0_
, test_id1_
);
1424 // Lose the context on the impl thread before the commit.
1425 PostLoseContextToImplThread();
1428 // Clear the manager of resources.
1429 ui_resource_
= nullptr;
1430 PostSetNeedsCommitToMainThread();
1434 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1435 test_id0_
= ui_resource_
->id();
1436 // Sanity check the UIResourceId should not be 0.
1437 EXPECT_NE(0, test_id0_
);
1438 // Usually ScopedUIResource are deleted from the manager in their
1439 // destructor (so usually ui_resource_ = nullptr). But here we need
1440 // ui_resource_ for the next step, so call DeleteUIResource directly.
1441 layer_tree_host()->DeleteUIResource(test_id0_
);
1442 // Delete the resouce and then lose the context.
1443 PostLoseContextToImplThread();
1446 // Release resource before ending the test.
1447 ui_resource_
= nullptr;
1456 void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) override
{
1457 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1458 switch (time_step_
) {
1460 // Sequence 1 (continued):
1461 // The first context lost happens before the resources were created,
1462 // and because it resulted in no resources being destroyed, it does not
1463 // trigger resource re-creation.
1464 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1465 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1466 // Resource Id on the impl-side has been created.
1467 PostSetNeedsCommitToMainThread();
1470 // Sequence 2 (continued):
1471 // The previous resource should have been deleted.
1472 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(test_id0_
));
1473 // The second resource should have been created.
1474 EXPECT_NE(0u, impl
->ResourceIdForUIResource(test_id1_
));
1475 // The second resource called the resource callback once and since the
1476 // context is lost, a "resource lost" callback was also issued.
1477 EXPECT_EQ(2, ui_resource_
->resource_create_count
);
1478 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1481 // Sequence 3 (continued):
1482 // Expect the resource callback to have been called once.
1483 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1484 // No "resource lost" callbacks.
1485 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1486 // The UI resource id should not be valid
1487 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(test_id0_
));
1493 UIResourceId test_id0_
;
1494 UIResourceId test_id1_
;
1497 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit
);
1499 // Losing UI resource before the pending trees is activated but after the
1500 // commit. Impl-side-painting only.
1501 class UIResourceLostBeforeActivateTree
: public UIResourceLostTest
{
1502 void StepCompleteOnMainThread(int step
) override
{
1503 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1506 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1507 PostSetNeedsCommitToMainThread();
1510 test_id_
= ui_resource_
->id();
1511 ui_resource_
= nullptr;
1512 PostSetNeedsCommitToMainThread();
1515 // Release resource before ending the test.
1516 ui_resource_
= nullptr;
1520 // Make sure no extra commits happened.
1525 void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) override
{
1526 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1527 switch (time_step_
) {
1529 PostSetNeedsCommitToMainThread();
1532 PostSetNeedsCommitToMainThread();
1537 void WillActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
1538 switch (time_step_
) {
1540 // The resource creation callback has been called.
1541 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1542 // The resource is not yet lost (sanity check).
1543 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1544 // The resource should not have been created yet on the impl-side.
1545 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1554 void DidActivateTreeOnThread(LayerTreeHostImpl
* impl
) override
{
1555 LayerTreeHostContextTest::DidActivateTreeOnThread(impl
);
1556 switch (time_step_
) {
1558 // The pending requests on the impl-side should have been processed.
1559 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1562 // The "lost resource" callback should have been called once.
1563 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1566 // The resource is deleted and should not be in the manager. Use
1567 // test_id_ since ui_resource_ has been deleted.
1568 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(test_id_
));
1572 PostStepCompleteToMainThread();
1577 UIResourceId test_id_
;
1580 TEST_F(UIResourceLostBeforeActivateTree
,
1581 RunMultiThread_DirectRenderer_ImplSidePaint
) {
1582 RunTest(true, false, true);
1585 TEST_F(UIResourceLostBeforeActivateTree
,
1586 RunMultiThread_DelegatingRenderer_ImplSidePaint
) {
1587 RunTest(true, true, true);
1590 // Resources evicted explicitly and by visibility changes.
1591 class UIResourceLostEviction
: public UIResourceLostTestSimple
{
1593 void StepCompleteOnMainThread(int step
) override
{
1594 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1597 ui_resource_
= FakeScopedUIResource::Create(layer_tree_host());
1598 EXPECT_NE(0, ui_resource_
->id());
1599 PostSetNeedsCommitToMainThread();
1602 // Make the tree not visible.
1603 PostSetVisibleToMainThread(false);
1606 // Release resource before ending the test.
1607 ui_resource_
= nullptr;
1615 void DidSetVisibleOnImplTree(LayerTreeHostImpl
* impl
, bool visible
) override
{
1616 TestWebGraphicsContext3D
* context
= TestContext();
1618 // All resources should have been evicted.
1619 ASSERT_EQ(0u, context
->NumTextures());
1620 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1621 EXPECT_EQ(2, ui_resource_
->resource_create_count
);
1622 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1623 // Drawing is disabled both because of the evicted resources and
1624 // because the renderer is not visible.
1625 EXPECT_FALSE(impl
->CanDraw());
1626 // Make the renderer visible again.
1627 PostSetVisibleToMainThread(true);
1631 void StepCompleteOnImplThread(LayerTreeHostImpl
* impl
) override
{
1632 TestWebGraphicsContext3D
* context
= TestContext();
1633 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1634 switch (time_step_
) {
1636 // The resource should have been created on LTHI after the commit.
1637 ASSERT_EQ(1u, context
->NumTextures());
1638 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1639 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1640 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1641 EXPECT_TRUE(impl
->CanDraw());
1642 // Evict all UI resources. This will trigger a commit.
1643 impl
->EvictAllUIResources();
1644 ASSERT_EQ(0u, context
->NumTextures());
1645 EXPECT_EQ(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1646 EXPECT_EQ(1, ui_resource_
->resource_create_count
);
1647 EXPECT_EQ(0, ui_resource_
->lost_resource_count
);
1648 EXPECT_FALSE(impl
->CanDraw());
1651 // The resource should have been recreated.
1652 ASSERT_EQ(1u, context
->NumTextures());
1653 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1654 EXPECT_EQ(2, ui_resource_
->resource_create_count
);
1655 EXPECT_EQ(1, ui_resource_
->lost_resource_count
);
1656 EXPECT_TRUE(impl
->CanDraw());
1659 // The resource should have been recreated after visibility was
1661 ASSERT_EQ(1u, context
->NumTextures());
1662 EXPECT_NE(0u, impl
->ResourceIdForUIResource(ui_resource_
->id()));
1663 EXPECT_EQ(3, ui_resource_
->resource_create_count
);
1664 EXPECT_EQ(2, ui_resource_
->lost_resource_count
);
1665 EXPECT_TRUE(impl
->CanDraw());
1671 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction
);
1673 class LayerTreeHostContextTestSurfaceCreateCallback
1674 : public LayerTreeHostContextTest
{
1676 LayerTreeHostContextTestSurfaceCreateCallback()
1677 : LayerTreeHostContextTest() {}
1679 void SetupTree() override
{
1680 if (layer_tree_host()->settings().impl_side_painting
) {
1681 picture_layer_
= FakePictureLayer::Create(&client_
);
1682 picture_layer_
->SetBounds(gfx::Size(10, 20));
1683 layer_tree_host()->SetRootLayer(picture_layer_
);
1685 content_layer_
= FakeContentLayer::Create(&client_
);
1686 content_layer_
->SetBounds(gfx::Size(10, 20));
1687 layer_tree_host()->SetRootLayer(content_layer_
);
1690 LayerTreeHostContextTest::SetupTree();
1693 void BeginTest() override
{ PostSetNeedsCommitToMainThread(); }
1695 void DidCommit() override
{
1696 switch (layer_tree_host()->source_frame_number()) {
1698 if (layer_tree_host()->settings().impl_side_painting
)
1699 EXPECT_EQ(1u, picture_layer_
->output_surface_created_count());
1701 EXPECT_EQ(1u, content_layer_
->output_surface_created_count());
1702 layer_tree_host()->SetNeedsCommit();
1705 if (layer_tree_host()->settings().impl_side_painting
)
1706 EXPECT_EQ(1u, picture_layer_
->output_surface_created_count());
1708 EXPECT_EQ(1u, content_layer_
->output_surface_created_count());
1709 layer_tree_host()->SetNeedsCommit();
1712 if (layer_tree_host()->settings().impl_side_painting
)
1713 EXPECT_EQ(1u, picture_layer_
->output_surface_created_count());
1715 EXPECT_EQ(1u, content_layer_
->output_surface_created_count());
1718 if (layer_tree_host()->settings().impl_side_painting
)
1719 EXPECT_EQ(2u, picture_layer_
->output_surface_created_count());
1721 EXPECT_EQ(2u, content_layer_
->output_surface_created_count());
1722 layer_tree_host()->SetNeedsCommit();
1727 void CommitCompleteOnThread(LayerTreeHostImpl
* impl
) override
{
1728 LayerTreeHostContextTest::CommitCompleteOnThread(impl
);
1729 switch (LastCommittedSourceFrameNumber(impl
)) {
1743 void AfterTest() override
{}
1746 FakeContentLayerClient client_
;
1747 scoped_refptr
<FakePictureLayer
> picture_layer_
;
1748 scoped_refptr
<FakeContentLayer
> content_layer_
;
1751 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback
);
1753 class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
1754 : public LayerTreeHostContextTest
{
1756 void BeginTest() override
{
1758 PostSetNeedsCommitToMainThread();
1761 void ScheduledActionWillSendBeginMainFrame() override
{
1766 // Defer commits before the BeginFrame arrives, causing it to be delayed.
1767 PostSetDeferCommitsToMainThread(true);
1768 // Meanwhile, lose the context while we are in defer commits.
1769 ImplThreadTaskRunner()->PostTask(
1771 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1772 LoseContextOnImplThread
,
1773 base::Unretained(this)));
1776 void LoseContextOnImplThread() {
1779 // After losing the context, stop deferring commits.
1780 PostSetDeferCommitsToMainThread(false);
1783 void WillBeginMainFrame() override
{
1784 // Don't begin a frame with a lost surface.
1785 EXPECT_FALSE(layer_tree_host()->output_surface_lost());
1788 void DidCommitAndDrawFrame() override
{ EndTest(); }
1790 void AfterTest() override
{}
1795 SINGLE_AND_MULTI_THREAD_TEST_F(
1796 LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
);