[Eraser strings] Remove unused Supervised User infobar and corresponding strings
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_context.cc
blobb5799bc4ca33706f63ace563d51724a896efaba3
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/delegated_frame_provider.h"
9 #include "cc/layers/delegated_frame_resource_collection.h"
10 #include "cc/layers/heads_up_display_layer.h"
11 #include "cc/layers/io_surface_layer.h"
12 #include "cc/layers/layer_impl.h"
13 #include "cc/layers/painted_scrollbar_layer.h"
14 #include "cc/layers/picture_layer.h"
15 #include "cc/layers/texture_layer.h"
16 #include "cc/layers/texture_layer_impl.h"
17 #include "cc/layers/video_layer.h"
18 #include "cc/layers/video_layer_impl.h"
19 #include "cc/output/filter_operations.h"
20 #include "cc/resources/single_release_callback.h"
21 #include "cc/test/failure_output_surface.h"
22 #include "cc/test/fake_content_layer_client.h"
23 #include "cc/test/fake_delegated_renderer_layer.h"
24 #include "cc/test/fake_delegated_renderer_layer_impl.h"
25 #include "cc/test/fake_layer_tree_host_client.h"
26 #include "cc/test/fake_output_surface.h"
27 #include "cc/test/fake_output_surface_client.h"
28 #include "cc/test/fake_painted_scrollbar_layer.h"
29 #include "cc/test/fake_picture_layer.h"
30 #include "cc/test/fake_picture_layer_impl.h"
31 #include "cc/test/fake_resource_provider.h"
32 #include "cc/test/fake_scoped_ui_resource.h"
33 #include "cc/test/fake_scrollbar.h"
34 #include "cc/test/fake_video_frame_provider.h"
35 #include "cc/test/layer_tree_test.h"
36 #include "cc/test/render_pass_test_common.h"
37 #include "cc/test/test_context_provider.h"
38 #include "cc/test/test_shared_bitmap_manager.h"
39 #include "cc/test/test_web_graphics_context_3d.h"
40 #include "cc/trees/layer_tree_host_impl.h"
41 #include "cc/trees/layer_tree_impl.h"
42 #include "cc/trees/single_thread_proxy.h"
43 #include "gpu/GLES2/gl2extchromium.h"
44 #include "media/base/media.h"
46 using media::VideoFrame;
48 namespace cc {
49 namespace {
51 // These tests deal with losing the 3d graphics context.
52 class LayerTreeHostContextTest : public LayerTreeTest {
53 public:
54 LayerTreeHostContextTest()
55 : LayerTreeTest(),
56 context3d_(NULL),
57 times_to_fail_create_(0),
58 times_to_lose_during_commit_(0),
59 times_to_lose_during_draw_(0),
60 times_to_fail_recreate_(0),
61 times_to_expect_create_failed_(0),
62 times_create_failed_(0),
63 committed_at_least_once_(false),
64 context_should_support_io_surface_(false),
65 fallback_context_works_(false),
66 async_output_surface_creation_(false) {
67 media::InitializeMediaLibrary();
70 void LoseContext() {
71 // CreateFakeOutputSurface happens on a different thread, so lock context3d_
72 // to make sure we don't set it to null after recreating it there.
73 base::AutoLock lock(context3d_lock_);
74 // For sanity-checking tests, they should only call this when the
75 // context is not lost.
76 CHECK(context3d_);
77 context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
78 GL_INNOCENT_CONTEXT_RESET_ARB);
79 context3d_ = NULL;
82 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
83 return TestWebGraphicsContext3D::Create();
86 scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
87 if (times_to_fail_create_) {
88 --times_to_fail_create_;
89 ExpectCreateToFail();
90 return make_scoped_ptr(new FailureOutputSurface(delegating_renderer()));
93 scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
94 base::AutoLock lock(context3d_lock_);
95 context3d_ = context3d.get();
97 if (context_should_support_io_surface_) {
98 context3d_->set_have_extension_io_surface(true);
99 context3d_->set_have_extension_egl_image(true);
102 if (delegating_renderer())
103 return FakeOutputSurface::CreateDelegating3d(context3d.Pass());
104 else
105 return FakeOutputSurface::Create3d(context3d.Pass());
108 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
109 LayerTreeHostImpl::FrameData* frame,
110 DrawResult draw_result) override {
111 if (draw_result == DRAW_ABORTED_MISSING_HIGH_RES_CONTENT) {
112 // Only valid for single-threaded compositing, which activates
113 // immediately and will try to draw again when content has finished.
114 DCHECK(!host_impl->proxy()->HasImplThread());
115 return draw_result;
117 EXPECT_EQ(DRAW_SUCCESS, draw_result);
118 if (!times_to_lose_during_draw_)
119 return draw_result;
121 --times_to_lose_during_draw_;
122 LoseContext();
124 times_to_fail_create_ = times_to_fail_recreate_;
125 times_to_fail_recreate_ = 0;
127 return draw_result;
130 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
131 committed_at_least_once_ = true;
133 if (!times_to_lose_during_commit_)
134 return;
135 --times_to_lose_during_commit_;
136 LoseContext();
138 times_to_fail_create_ = times_to_fail_recreate_;
139 times_to_fail_recreate_ = 0;
142 void DidFailToInitializeOutputSurface() override { ++times_create_failed_; }
144 void TearDown() override {
145 LayerTreeTest::TearDown();
146 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
149 void ExpectCreateToFail() { ++times_to_expect_create_failed_; }
151 protected:
152 // Protects use of context3d_ so LoseContext and CreateFakeOutputSurface
153 // can both use it on different threads.
154 base::Lock context3d_lock_;
155 TestWebGraphicsContext3D* context3d_;
157 int times_to_fail_create_;
158 int times_to_lose_during_commit_;
159 int times_to_lose_during_draw_;
160 int times_to_fail_recreate_;
161 int times_to_expect_create_failed_;
162 int times_create_failed_;
163 bool committed_at_least_once_;
164 bool context_should_support_io_surface_;
165 bool fallback_context_works_;
166 bool async_output_surface_creation_;
169 class LayerTreeHostContextTestLostContextSucceeds
170 : public LayerTreeHostContextTest {
171 public:
172 LayerTreeHostContextTestLostContextSucceeds()
173 : LayerTreeHostContextTest(),
174 test_case_(0),
175 num_losses_(0),
176 num_losses_last_test_case_(-1),
177 recovered_context_(true),
178 first_initialized_(false) {}
180 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
182 void RequestNewOutputSurface() override {
183 if (async_output_surface_creation_) {
184 MainThreadTaskRunner()->PostTask(
185 FROM_HERE, base::Bind(&LayerTreeHostContextTestLostContextSucceeds::
186 CreateAndSetOutputSurface,
187 base::Unretained(this)));
188 } else {
189 CreateAndSetOutputSurface();
193 void CreateAndSetOutputSurface() {
194 scoped_ptr<OutputSurface> surface(
195 LayerTreeHostContextTest::CreateOutputSurface());
196 CHECK(surface);
197 layer_tree_host()->SetOutputSurface(surface.Pass());
200 void DidInitializeOutputSurface() override {
201 if (first_initialized_)
202 ++num_losses_;
203 else
204 first_initialized_ = true;
206 recovered_context_ = true;
209 void AfterTest() override { EXPECT_EQ(11u, test_case_); }
211 void DidCommitAndDrawFrame() override {
212 // If the last frame had a context loss, then we'll commit again to
213 // recover.
214 if (!recovered_context_)
215 return;
216 if (times_to_lose_during_commit_)
217 return;
218 if (times_to_lose_during_draw_)
219 return;
221 recovered_context_ = false;
222 if (NextTestCase())
223 InvalidateAndSetNeedsCommit();
224 else
225 EndTest();
228 virtual void InvalidateAndSetNeedsCommit() {
229 // Cause damage so we try to draw.
230 layer_tree_host()->root_layer()->SetNeedsDisplay();
231 layer_tree_host()->SetNeedsCommit();
234 bool NextTestCase() {
235 static const TestCase kTests[] = {
236 // Losing the context and failing to recreate it (or losing it again
237 // immediately) a small number of times should succeed.
239 1, // times_to_lose_during_commit
240 0, // times_to_lose_during_draw
241 0, // times_to_fail_recreate
242 false, // fallback_context_works
243 false, // async_output_surface_creation
246 0, // times_to_lose_during_commit
247 1, // times_to_lose_during_draw
248 0, // times_to_fail_recreate
249 false, // fallback_context_works
250 false, // async_output_surface_creation
253 1, // times_to_lose_during_commit
254 0, // times_to_lose_during_draw
255 3, // times_to_fail_recreate
256 false, // fallback_context_works
257 false, // async_output_surface_creation
260 0, // times_to_lose_during_commit
261 1, // times_to_lose_during_draw
262 3, // times_to_fail_recreate
263 false, // fallback_context_works
264 false, // async_output_surface_creation
267 0, // times_to_lose_during_commit
268 1, // times_to_lose_during_draw
269 3, // times_to_fail_recreate
270 false, // fallback_context_works
271 true, // async_output_surface_creation
273 // Losing the context and recreating it any number of times should
274 // succeed.
276 10, // times_to_lose_during_commit
277 0, // times_to_lose_during_draw
278 0, // times_to_fail_recreate
279 false, // fallback_context_works
280 false, // async_output_surface_creation
283 0, // times_to_lose_during_commit
284 10, // times_to_lose_during_draw
285 0, // times_to_fail_recreate
286 false, // fallback_context_works
287 false, // async_output_surface_creation
290 10, // times_to_lose_during_commit
291 0, // times_to_lose_during_draw
292 0, // times_to_fail_recreate
293 false, // fallback_context_works
294 true, // async_output_surface_creation
297 0, // times_to_lose_during_commit
298 10, // times_to_lose_during_draw
299 0, // times_to_fail_recreate
300 false, // fallback_context_works
301 true, // async_output_surface_creation
303 // Losing the context, failing to reinitialize it, and making a fallback
304 // context should work.
306 0, // times_to_lose_during_commit
307 1, // times_to_lose_during_draw
308 0, // times_to_fail_recreate
309 true, // fallback_context_works
310 false, // async_output_surface_creation
313 0, // times_to_lose_during_commit
314 1, // times_to_lose_during_draw
315 0, // times_to_fail_recreate
316 true, // fallback_context_works
317 true, // async_output_surface_creation
321 if (test_case_ >= arraysize(kTests))
322 return false;
323 // Make sure that we lost our context at least once in the last test run so
324 // the test did something.
325 EXPECT_GT(num_losses_, num_losses_last_test_case_);
326 num_losses_last_test_case_ = num_losses_;
328 times_to_lose_during_commit_ =
329 kTests[test_case_].times_to_lose_during_commit;
330 times_to_lose_during_draw_ = kTests[test_case_].times_to_lose_during_draw;
331 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
332 fallback_context_works_ = kTests[test_case_].fallback_context_works;
333 async_output_surface_creation_ =
334 kTests[test_case_].async_output_surface_creation;
335 ++test_case_;
336 return true;
339 struct TestCase {
340 int times_to_lose_during_commit;
341 int times_to_lose_during_draw;
342 int times_to_fail_recreate;
343 bool fallback_context_works;
344 bool async_output_surface_creation;
347 protected:
348 size_t test_case_;
349 int num_losses_;
350 int num_losses_last_test_case_;
351 bool recovered_context_;
352 bool first_initialized_;
355 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
357 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
358 : public LayerTreeHostContextTest {
359 public:
360 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
361 : LayerTreeHostContextTest() {}
363 void WillBeginTest() override {
364 // Override and do not signal SetLayerTreeHostClientReady.
367 void BeginTest() override {
368 PostSetNeedsCommitToMainThread();
369 EndTest();
372 scoped_ptr<OutputSurface> CreateOutputSurface() override {
373 EXPECT_TRUE(false);
374 return nullptr;
377 void DidInitializeOutputSurface() override { EXPECT_TRUE(false); }
379 void AfterTest() override {}
382 SINGLE_AND_MULTI_THREAD_TEST_F(
383 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
385 class MultipleCompositeDoesNotCreateOutputSurface
386 : public LayerTreeHostContextTest {
387 public:
388 MultipleCompositeDoesNotCreateOutputSurface()
389 : LayerTreeHostContextTest(), request_count_(0) {}
391 void InitializeSettings(LayerTreeSettings* settings) override {
392 settings->single_thread_proxy_scheduler = false;
393 settings->use_zero_copy = true;
394 settings->use_one_copy = false;
397 void RequestNewOutputSurface() override {
398 EXPECT_GE(1, ++request_count_);
399 EndTest();
402 void BeginTest() override {
403 layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1));
404 layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(2));
407 scoped_ptr<OutputSurface> CreateOutputSurface() override {
408 EXPECT_TRUE(false);
409 return nullptr;
412 void DidInitializeOutputSurface() override { EXPECT_TRUE(false); }
414 void AfterTest() override {}
416 int request_count_;
419 // This test uses Composite() which only exists for single thread.
420 SINGLE_THREAD_TEST_F(MultipleCompositeDoesNotCreateOutputSurface);
422 // This test makes sure that once a SingleThreadProxy issues a
423 // DidFailToInitializeOutputSurface, that future Composite calls will not
424 // trigger additional requests for output surfaces.
425 class FailedCreateDoesNotCreateExtraOutputSurface
426 : public LayerTreeHostContextTest {
427 public:
428 FailedCreateDoesNotCreateExtraOutputSurface()
429 : LayerTreeHostContextTest(), num_requests_(0), has_failed_(false) {}
431 void InitializeSettings(LayerTreeSettings* settings) override {
432 settings->single_thread_proxy_scheduler = false;
433 settings->use_zero_copy = true;
434 settings->use_one_copy = false;
437 void RequestNewOutputSurface() override {
438 num_requests_++;
439 // There should be one initial request and then one request from
440 // the LayerTreeTest test hooks DidFailToInitializeOutputSurface (which is
441 // hard to skip). This second request is just ignored and is test cruft.
442 EXPECT_LE(num_requests_, 2);
443 if (num_requests_ > 1)
444 return;
445 ExpectCreateToFail();
446 layer_tree_host()->SetOutputSurface(
447 make_scoped_ptr(new FailureOutputSurface(false)));
450 void BeginTest() override {
451 // First composite tries to create a surface.
452 layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1));
453 EXPECT_EQ(num_requests_, 2);
454 EXPECT_TRUE(has_failed_);
456 // Second composite should not request or fail.
457 layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(2));
458 EXPECT_EQ(num_requests_, 2);
459 EndTest();
462 void DidInitializeOutputSurface() override { EXPECT_TRUE(false); }
464 void DidFailToInitializeOutputSurface() override {
465 LayerTreeHostContextTest::DidFailToInitializeOutputSurface();
466 EXPECT_FALSE(has_failed_);
467 has_failed_ = true;
470 void AfterTest() override {}
472 int num_requests_;
473 bool has_failed_;
476 // This test uses Composite() which only exists for single thread.
477 SINGLE_THREAD_TEST_F(FailedCreateDoesNotCreateExtraOutputSurface);
479 class LayerTreeHostContextTestCommitAfterDelayedOutputSurface
480 : public LayerTreeHostContextTest {
481 public:
482 LayerTreeHostContextTestCommitAfterDelayedOutputSurface()
483 : LayerTreeHostContextTest(), creating_output_(false) {}
485 void InitializeSettings(LayerTreeSettings* settings) override {
486 settings->single_thread_proxy_scheduler = false;
487 settings->use_zero_copy = true;
488 settings->use_one_copy = false;
491 void RequestNewOutputSurface() override {
492 MainThreadTaskRunner()->PostTask(
493 FROM_HERE,
494 base::Bind(&LayerTreeHostContextTestCommitAfterDelayedOutputSurface::
495 CreateAndSetOutputSurface,
496 base::Unretained(this)));
499 void CreateAndSetOutputSurface() {
500 creating_output_ = true;
501 layer_tree_host()->SetOutputSurface(
502 LayerTreeHostContextTest::CreateOutputSurface());
505 void BeginTest() override {
506 layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1));
509 void ScheduleComposite() override {
510 if (creating_output_)
511 EndTest();
514 void AfterTest() override {}
516 bool creating_output_;
519 // This test uses Composite() which only exists for single thread.
520 SINGLE_THREAD_TEST_F(LayerTreeHostContextTestCommitAfterDelayedOutputSurface);
522 class LayerTreeHostContextTestAvoidUnnecessaryComposite
523 : public LayerTreeHostContextTest {
524 public:
525 LayerTreeHostContextTestAvoidUnnecessaryComposite()
526 : LayerTreeHostContextTest(), in_composite_(false) {}
528 void InitializeSettings(LayerTreeSettings* settings) override {
529 settings->single_thread_proxy_scheduler = false;
530 settings->use_zero_copy = true;
531 settings->use_one_copy = false;
534 void RequestNewOutputSurface() override {
535 layer_tree_host()->SetOutputSurface(
536 LayerTreeHostContextTest::CreateOutputSurface());
537 EndTest();
540 void BeginTest() override {
541 in_composite_ = true;
542 layer_tree_host()->Composite(base::TimeTicks::FromInternalValue(1));
543 in_composite_ = false;
546 void ScheduleComposite() override { EXPECT_FALSE(in_composite_); }
548 void AfterTest() override {}
550 bool in_composite_;
553 // This test uses Composite() which only exists for single thread.
554 SINGLE_THREAD_TEST_F(LayerTreeHostContextTestAvoidUnnecessaryComposite);
556 // This test uses PictureLayer to check for a working context.
557 class LayerTreeHostContextTestLostContextSucceedsWithContent
558 : public LayerTreeHostContextTestLostContextSucceeds {
559 public:
560 void SetupTree() override {
561 root_ = Layer::Create(layer_settings());
562 root_->SetBounds(gfx::Size(10, 10));
563 root_->SetIsDrawable(true);
565 // Paint non-solid color.
566 SkPaint paint;
567 paint.setColor(SkColorSetARGB(100, 80, 200, 200));
568 client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint);
570 layer_ = FakePictureLayer::Create(layer_settings(), &client_);
571 layer_->SetBounds(gfx::Size(10, 10));
572 layer_->SetIsDrawable(true);
574 root_->AddChild(layer_);
576 layer_tree_host()->SetRootLayer(root_);
577 LayerTreeHostContextTest::SetupTree();
580 void InvalidateAndSetNeedsCommit() override {
581 // Invalidate the render surface so we don't try to use a cached copy of the
582 // surface. We want to make sure to test the drawing paths for drawing to
583 // a child surface.
584 layer_->SetNeedsDisplay();
585 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
588 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
589 FakePictureLayerImpl* picture_impl = static_cast<FakePictureLayerImpl*>(
590 host_impl->active_tree()->root_layer()->children()[0]);
591 EXPECT_TRUE(picture_impl->HighResTiling()
592 ->TileAt(0, 0)
593 ->draw_info()
594 .IsReadyToDraw());
597 protected:
598 FakeContentLayerClient client_;
599 scoped_refptr<Layer> root_;
600 scoped_refptr<Layer> layer_;
603 SINGLE_AND_MULTI_THREAD_TEST_F(
604 LayerTreeHostContextTestLostContextSucceedsWithContent);
606 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
607 : public LayerTreeHostContextTest {
608 public:
609 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
610 : times_to_fail_(1), times_initialized_(0) {
611 times_to_fail_create_ = times_to_fail_;
614 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
616 void DidInitializeOutputSurface() override { times_initialized_++; }
618 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EndTest(); }
620 void AfterTest() override {
621 EXPECT_EQ(times_to_fail_, times_create_failed_);
622 EXPECT_NE(0, times_initialized_);
625 private:
626 int times_to_fail_;
627 int times_initialized_;
630 SINGLE_AND_MULTI_THREAD_TEST_F(
631 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce);
633 class LayerTreeHostContextTestLostContextAndEvictTextures
634 : public LayerTreeHostContextTest {
635 public:
636 LayerTreeHostContextTestLostContextAndEvictTextures()
637 : LayerTreeHostContextTest(),
638 impl_host_(0),
639 num_commits_(0),
640 lost_context_(false) {}
642 void SetupTree() override {
643 // Paint non-solid color.
644 SkPaint paint;
645 paint.setColor(SkColorSetARGB(100, 80, 200, 200));
646 client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint);
648 scoped_refptr<FakePictureLayer> picture_layer =
649 FakePictureLayer::Create(layer_settings(), &client_);
650 picture_layer->SetBounds(gfx::Size(10, 20));
651 layer_tree_host()->SetRootLayer(picture_layer);
653 LayerTreeHostContextTest::SetupTree();
656 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
658 void PostEvictTextures() {
659 if (HasImplThread()) {
660 ImplThreadTaskRunner()->PostTask(
661 FROM_HERE,
662 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
663 EvictTexturesOnImplThread,
664 base::Unretained(this)));
665 } else {
666 DebugScopedSetImplThread impl(proxy());
667 EvictTexturesOnImplThread();
671 void EvictTexturesOnImplThread() {
672 impl_host_->EvictTexturesForTesting();
674 if (lose_after_evict_) {
675 LoseContext();
676 lost_context_ = true;
680 void DidCommitAndDrawFrame() override {
681 if (num_commits_ > 1)
682 return;
683 PostEvictTextures();
686 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
687 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
688 if (num_commits_ > 1)
689 return;
690 ++num_commits_;
691 if (!lose_after_evict_) {
692 LoseContext();
693 lost_context_ = true;
697 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
698 FakePictureLayerImpl* picture_impl =
699 static_cast<FakePictureLayerImpl*>(impl->active_tree()->root_layer());
700 EXPECT_TRUE(picture_impl->HighResTiling()
701 ->TileAt(0, 0)
702 ->draw_info()
703 .IsReadyToDraw());
705 impl_host_ = impl;
706 if (lost_context_)
707 EndTest();
710 void DidInitializeOutputSurface() override {}
712 void AfterTest() override {}
714 protected:
715 bool lose_after_evict_;
716 FakeContentLayerClient client_;
717 LayerTreeHostImpl* impl_host_;
718 int num_commits_;
719 bool lost_context_;
722 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
723 LoseAfterEvict_SingleThread_DirectRenderer) {
724 lose_after_evict_ = true;
725 RunTest(false, false);
728 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
729 LoseAfterEvict_SingleThread_DelegatingRenderer) {
730 lose_after_evict_ = true;
731 RunTest(false, true);
734 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
735 LoseAfterEvict_MultiThread_DirectRenderer) {
736 lose_after_evict_ = true;
737 RunTest(true, false);
740 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
741 LoseAfterEvict_MultiThread_DelegatingRenderer) {
742 lose_after_evict_ = true;
743 RunTest(true, true);
746 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
747 LoseBeforeEvict_SingleThread_DirectRenderer) {
748 lose_after_evict_ = false;
749 RunTest(false, false);
752 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
753 LoseBeforeEvict_SingleThread_DelegatingRenderer) {
754 lose_after_evict_ = false;
755 RunTest(false, true);
758 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
759 LoseBeforeEvict_MultiThread_DirectRenderer) {
760 lose_after_evict_ = false;
761 RunTest(true, false);
764 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
765 LoseBeforeEvict_MultiThread_DelegatingRenderer) {
766 lose_after_evict_ = false;
767 RunTest(true, true);
770 class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest {
771 public:
772 LayerTreeHostContextTestLayersNotified()
773 : LayerTreeHostContextTest(), num_commits_(0) {}
775 void SetupTree() override {
776 root_ = FakePictureLayer::Create(layer_settings(), &client_);
777 child_ = FakePictureLayer::Create(layer_settings(), &client_);
778 grandchild_ = FakePictureLayer::Create(layer_settings(), &client_);
780 root_->AddChild(child_);
781 child_->AddChild(grandchild_);
783 layer_tree_host()->SetRootLayer(root_);
784 LayerTreeHostContextTest::SetupTree();
787 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
789 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
790 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
792 FakePictureLayerImpl* root_picture = NULL;
793 FakePictureLayerImpl* child_picture = NULL;
794 FakePictureLayerImpl* grandchild_picture = NULL;
796 root_picture = static_cast<FakePictureLayerImpl*>(
797 host_impl->active_tree()->root_layer());
798 child_picture =
799 static_cast<FakePictureLayerImpl*>(root_picture->children()[0]);
800 grandchild_picture =
801 static_cast<FakePictureLayerImpl*>(child_picture->children()[0]);
803 ++num_commits_;
804 switch (num_commits_) {
805 case 1:
806 EXPECT_EQ(0u, root_picture->release_resources_count());
807 EXPECT_EQ(0u, child_picture->release_resources_count());
808 EXPECT_EQ(0u, grandchild_picture->release_resources_count());
810 // Lose the context and struggle to recreate it.
811 LoseContext();
812 times_to_fail_create_ = 1;
813 break;
814 case 2:
815 EXPECT_TRUE(root_picture->release_resources_count());
816 EXPECT_TRUE(child_picture->release_resources_count());
817 EXPECT_TRUE(grandchild_picture->release_resources_count());
819 EndTest();
820 break;
821 default:
822 NOTREACHED();
826 void AfterTest() override {}
828 private:
829 int num_commits_;
831 FakeContentLayerClient client_;
832 scoped_refptr<Layer> root_;
833 scoped_refptr<Layer> child_;
834 scoped_refptr<Layer> grandchild_;
837 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
839 class LayerTreeHostContextTestDontUseLostResources
840 : public LayerTreeHostContextTest {
841 public:
842 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
843 context_should_support_io_surface_ = true;
845 child_output_surface_ = FakeOutputSurface::Create3d();
846 child_output_surface_->BindToClient(&output_surface_client_);
847 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
848 child_resource_provider_ = FakeResourceProvider::Create(
849 child_output_surface_.get(), shared_bitmap_manager_.get());
852 static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
854 void SetupTree() override {
855 gpu::gles2::GLES2Interface* gl =
856 child_output_surface_->context_provider()->ContextGL();
858 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
860 scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
861 pass_for_quad->SetNew(
862 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
863 RenderPassId(2, 1),
864 gfx::Rect(0, 0, 10, 10),
865 gfx::Rect(0, 0, 10, 10),
866 gfx::Transform());
868 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
869 pass->SetNew(RenderPassId(1, 1),
870 gfx::Rect(0, 0, 10, 10),
871 gfx::Rect(0, 0, 10, 10),
872 gfx::Transform());
873 pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
874 RenderPassId(2, 1));
876 frame_data->render_pass_list.push_back(pass_for_quad.Pass());
877 frame_data->render_pass_list.push_back(pass.Pass());
879 delegated_resource_collection_ = new DelegatedFrameResourceCollection;
880 delegated_frame_provider_ = new DelegatedFrameProvider(
881 delegated_resource_collection_.get(), frame_data.Pass());
883 ResourceId resource = child_resource_provider_->CreateResource(
884 gfx::Size(4, 4), GL_CLAMP_TO_EDGE,
885 ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888);
886 ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
887 resource);
889 gpu::Mailbox mailbox;
890 gl->GenMailboxCHROMIUM(mailbox.name);
891 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
893 scoped_refptr<Layer> root = Layer::Create(layer_settings());
894 root->SetBounds(gfx::Size(10, 10));
895 root->SetIsDrawable(true);
897 scoped_refptr<FakeDelegatedRendererLayer> delegated =
898 FakeDelegatedRendererLayer::Create(layer_settings(),
899 delegated_frame_provider_.get());
900 delegated->SetBounds(gfx::Size(10, 10));
901 delegated->SetIsDrawable(true);
902 root->AddChild(delegated);
904 scoped_refptr<PictureLayer> layer =
905 PictureLayer::Create(layer_settings(), &client_);
906 layer->SetBounds(gfx::Size(10, 10));
907 layer->SetIsDrawable(true);
908 root->AddChild(layer);
910 scoped_refptr<TextureLayer> texture =
911 TextureLayer::CreateForMailbox(layer_settings_, NULL);
912 texture->SetBounds(gfx::Size(10, 10));
913 texture->SetIsDrawable(true);
914 texture->SetTextureMailbox(
915 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
916 SingleReleaseCallback::Create(
917 base::Bind(&LayerTreeHostContextTestDontUseLostResources::
918 EmptyReleaseCallback)));
919 root->AddChild(texture);
921 scoped_refptr<PictureLayer> mask =
922 PictureLayer::Create(layer_settings_, &client_);
923 mask->SetBounds(gfx::Size(10, 10));
925 scoped_refptr<PictureLayer> layer_with_mask =
926 PictureLayer::Create(layer_settings_, &client_);
927 layer_with_mask->SetBounds(gfx::Size(10, 10));
928 layer_with_mask->SetIsDrawable(true);
929 layer_with_mask->SetMaskLayer(mask.get());
930 root->AddChild(layer_with_mask);
932 scoped_refptr<VideoLayer> video_color = VideoLayer::Create(
933 layer_settings_, &color_frame_provider_, media::VIDEO_ROTATION_0);
934 video_color->SetBounds(gfx::Size(10, 10));
935 video_color->SetIsDrawable(true);
936 root->AddChild(video_color);
938 scoped_refptr<VideoLayer> video_hw = VideoLayer::Create(
939 layer_settings_, &hw_frame_provider_, media::VIDEO_ROTATION_0);
940 video_hw->SetBounds(gfx::Size(10, 10));
941 video_hw->SetIsDrawable(true);
942 root->AddChild(video_hw);
944 scoped_refptr<VideoLayer> video_scaled_hw = VideoLayer::Create(
945 layer_settings_, &scaled_hw_frame_provider_, media::VIDEO_ROTATION_0);
946 video_scaled_hw->SetBounds(gfx::Size(10, 10));
947 video_scaled_hw->SetIsDrawable(true);
948 root->AddChild(video_scaled_hw);
950 color_video_frame_ = VideoFrame::CreateColorFrame(
951 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
952 hw_video_frame_ = VideoFrame::WrapNativeTexture(
953 media::PIXEL_FORMAT_ARGB,
954 gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point),
955 media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
956 gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4), base::TimeDelta());
957 scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
958 media::PIXEL_FORMAT_ARGB,
959 gpu::MailboxHolder(mailbox, GL_TEXTURE_2D, sync_point),
960 media::VideoFrame::ReleaseMailboxCB(), gfx::Size(4, 4),
961 gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4), base::TimeDelta());
963 color_frame_provider_.set_frame(color_video_frame_);
964 hw_frame_provider_.set_frame(hw_video_frame_);
965 scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
967 scoped_refptr<IOSurfaceLayer> io_surface =
968 IOSurfaceLayer::Create(layer_settings_);
969 io_surface->SetBounds(gfx::Size(10, 10));
970 io_surface->SetIsDrawable(true);
971 io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10));
972 root->AddChild(io_surface);
974 // Enable the hud.
975 LayerTreeDebugState debug_state;
976 debug_state.show_property_changed_rects = true;
977 layer_tree_host()->SetDebugState(debug_state);
979 scoped_refptr<PaintedScrollbarLayer> scrollbar =
980 PaintedScrollbarLayer::Create(
981 layer_settings_, scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(),
982 layer->id());
983 scrollbar->SetBounds(gfx::Size(10, 10));
984 scrollbar->SetIsDrawable(true);
985 root->AddChild(scrollbar);
987 layer_tree_host()->SetRootLayer(root);
988 LayerTreeHostContextTest::SetupTree();
991 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
993 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
994 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
996 if (host_impl->active_tree()->source_frame_number() == 3) {
997 // On the third commit we're recovering from context loss. Hardware
998 // video frames should not be reused by the VideoFrameProvider, but
999 // software frames can be.
1000 hw_frame_provider_.set_frame(NULL);
1001 scaled_hw_frame_provider_.set_frame(NULL);
1005 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1006 LayerTreeHostImpl::FrameData* frame,
1007 DrawResult draw_result) override {
1008 if (host_impl->active_tree()->source_frame_number() == 2) {
1009 // Lose the context during draw on the second commit. This will cause
1010 // a third commit to recover.
1011 context3d_->set_times_bind_texture_succeeds(0);
1013 return draw_result;
1016 scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
1017 // This will get called twice:
1018 // First when we create the initial output surface...
1019 if (layer_tree_host()->source_frame_number() > 0) {
1020 // ... and then again after we forced the context to be lost.
1021 lost_context_ = true;
1023 return LayerTreeHostContextTest::CreateFakeOutputSurface();
1026 void DidCommitAndDrawFrame() override {
1027 ASSERT_TRUE(layer_tree_host()->hud_layer());
1028 // End the test once we know the 3nd frame drew.
1029 if (layer_tree_host()->source_frame_number() < 5) {
1030 layer_tree_host()->root_layer()->SetNeedsDisplay();
1031 layer_tree_host()->SetNeedsCommit();
1032 } else {
1033 EndTest();
1037 void AfterTest() override { EXPECT_TRUE(lost_context_); }
1039 private:
1040 FakeContentLayerClient client_;
1041 bool lost_context_;
1043 FakeOutputSurfaceClient output_surface_client_;
1044 scoped_ptr<FakeOutputSurface> child_output_surface_;
1045 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1046 scoped_ptr<ResourceProvider> child_resource_provider_;
1048 scoped_refptr<DelegatedFrameResourceCollection>
1049 delegated_resource_collection_;
1050 scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
1052 scoped_refptr<VideoFrame> color_video_frame_;
1053 scoped_refptr<VideoFrame> hw_video_frame_;
1054 scoped_refptr<VideoFrame> scaled_hw_video_frame_;
1056 FakeVideoFrameProvider color_frame_provider_;
1057 FakeVideoFrameProvider hw_frame_provider_;
1058 FakeVideoFrameProvider scaled_hw_frame_provider_;
1060 LayerSettings layer_settings_;
1063 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
1065 class LayerTreeHostContextTestImplSidePainting
1066 : public LayerTreeHostContextTest {
1067 public:
1068 void SetupTree() override {
1069 scoped_refptr<Layer> root = Layer::Create(layer_settings());
1070 root->SetBounds(gfx::Size(10, 10));
1071 root->SetIsDrawable(true);
1073 scoped_refptr<PictureLayer> picture =
1074 PictureLayer::Create(layer_settings(), &client_);
1075 picture->SetBounds(gfx::Size(10, 10));
1076 picture->SetIsDrawable(true);
1077 root->AddChild(picture);
1079 layer_tree_host()->SetRootLayer(root);
1080 LayerTreeHostContextTest::SetupTree();
1083 void BeginTest() override {
1084 times_to_lose_during_commit_ = 1;
1085 PostSetNeedsCommitToMainThread();
1088 void AfterTest() override {}
1090 void DidInitializeOutputSurface() override { EndTest(); }
1092 private:
1093 FakeContentLayerClient client_;
1096 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
1098 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1099 public:
1100 ScrollbarLayerLostContext() : commits_(0) {}
1102 void BeginTest() override {
1103 scoped_refptr<Layer> scroll_layer = Layer::Create(layer_settings());
1104 scrollbar_layer_ = FakePaintedScrollbarLayer::Create(
1105 layer_settings(), false, true, scroll_layer->id());
1106 scrollbar_layer_->SetBounds(gfx::Size(10, 100));
1107 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
1108 layer_tree_host()->root_layer()->AddChild(scroll_layer);
1109 PostSetNeedsCommitToMainThread();
1112 void AfterTest() override {}
1114 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
1115 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1117 ++commits_;
1118 switch (commits_) {
1119 case 1:
1120 // First (regular) update, we should upload 2 resources (thumb, and
1121 // backtrack).
1122 EXPECT_EQ(1, scrollbar_layer_->update_count());
1123 LoseContext();
1124 break;
1125 case 2:
1126 // Second update, after the lost context, we should still upload 2
1127 // resources even if the contents haven't changed.
1128 EXPECT_EQ(2, scrollbar_layer_->update_count());
1129 EndTest();
1130 break;
1131 default:
1132 NOTREACHED();
1136 private:
1137 int commits_;
1138 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
1141 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1143 class UIResourceLostTest : public LayerTreeHostContextTest {
1144 public:
1145 UIResourceLostTest() : time_step_(0) {}
1146 void InitializeSettings(LayerTreeSettings* settings) override {
1147 settings->renderer_settings.texture_id_allocation_chunk_size = 1;
1149 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1150 void AfterTest() override {}
1152 // This is called on the main thread after each commit and
1153 // DidActivateTreeOnThread, with the value of time_step_ at the time
1154 // of the call to DidActivateTreeOnThread. Similar tests will do
1155 // work on the main thread in DidCommit but that is unsuitable because
1156 // the main thread work for these tests must happen after
1157 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1158 // painting.
1159 virtual void StepCompleteOnMainThread(int time_step) = 0;
1161 // Called after DidActivateTreeOnThread. If this is done during the commit,
1162 // the call to StepCompleteOnMainThread will not occur until after
1163 // the commit completes, because the main thread is blocked.
1164 void PostStepCompleteToMainThread() {
1165 proxy()->MainThreadTaskRunner()->PostTask(
1166 FROM_HERE,
1167 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal,
1168 base::Unretained(this),
1169 time_step_));
1172 void PostLoseContextToImplThread() {
1173 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1174 ImplThreadTaskRunner()->PostTask(
1175 FROM_HERE,
1176 base::Bind(&LayerTreeHostContextTest::LoseContext,
1177 base::Unretained(this)));
1180 protected:
1181 int time_step_;
1182 scoped_ptr<FakeScopedUIResource> ui_resource_;
1184 private:
1185 void StepCompleteOnMainThreadInternal(int step) {
1186 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1187 StepCompleteOnMainThread(step);
1191 class UIResourceLostTestSimple : public UIResourceLostTest {
1192 public:
1193 // This is called when the new layer tree has been activated.
1194 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1196 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
1197 StepCompleteOnImplThread(impl);
1198 PostStepCompleteToMainThread();
1199 ++time_step_;
1203 // Losing context after an UI resource has been created.
1204 class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
1205 public:
1206 void StepCompleteOnMainThread(int step) override {
1207 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1208 switch (step) {
1209 case 0:
1210 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1211 // Expects a valid UIResourceId.
1212 EXPECT_NE(0, ui_resource_->id());
1213 PostSetNeedsCommitToMainThread();
1214 break;
1215 case 4:
1216 // Release resource before ending the test.
1217 ui_resource_ = nullptr;
1218 EndTest();
1219 break;
1220 case 5:
1221 NOTREACHED();
1222 break;
1226 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
1227 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1228 switch (time_step_) {
1229 case 1:
1230 // The resource should have been created on LTHI after the commit.
1231 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1232 PostSetNeedsCommitToMainThread();
1233 break;
1234 case 2:
1235 LoseContext();
1236 break;
1237 case 3:
1238 // The resources should have been recreated. The bitmap callback should
1239 // have been called once with the resource_lost flag set to true.
1240 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1241 // Resource Id on the impl-side have been recreated as well. Note
1242 // that the same UIResourceId persists after the context lost.
1243 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1244 PostSetNeedsCommitToMainThread();
1245 break;
1250 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
1252 // Losing context before UI resource requests can be commited. Three sequences
1253 // of creation/deletion are considered:
1254 // 1. Create one resource -> Context Lost => Expect the resource to have been
1255 // created.
1256 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1257 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1258 // test_id1_ to have been created.
1259 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1260 // the resource to not exist in the manager.
1261 class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
1262 public:
1263 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1265 void StepCompleteOnMainThread(int step) override {
1266 switch (step) {
1267 case 0:
1268 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1269 // Lose the context on the impl thread before the commit.
1270 PostLoseContextToImplThread();
1271 break;
1272 case 2:
1273 // Sequence 2:
1274 // Currently one resource has been created.
1275 test_id0_ = ui_resource_->id();
1276 // Delete this resource.
1277 ui_resource_ = nullptr;
1278 // Create another resource.
1279 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1280 test_id1_ = ui_resource_->id();
1281 // Sanity check that two resource creations return different ids.
1282 EXPECT_NE(test_id0_, test_id1_);
1283 // Lose the context on the impl thread before the commit.
1284 PostLoseContextToImplThread();
1285 break;
1286 case 3:
1287 // Clear the manager of resources.
1288 ui_resource_ = nullptr;
1289 PostSetNeedsCommitToMainThread();
1290 break;
1291 case 4:
1292 // Sequence 3:
1293 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1294 test_id0_ = ui_resource_->id();
1295 // Sanity check the UIResourceId should not be 0.
1296 EXPECT_NE(0, test_id0_);
1297 // Usually ScopedUIResource are deleted from the manager in their
1298 // destructor (so usually ui_resource_ = nullptr). But here we need
1299 // ui_resource_ for the next step, so call DeleteUIResource directly.
1300 layer_tree_host()->DeleteUIResource(test_id0_);
1301 // Delete the resouce and then lose the context.
1302 PostLoseContextToImplThread();
1303 break;
1304 case 5:
1305 // Release resource before ending the test.
1306 ui_resource_ = nullptr;
1307 EndTest();
1308 break;
1309 case 6:
1310 NOTREACHED();
1311 break;
1315 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
1316 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1317 switch (time_step_) {
1318 case 1:
1319 // Sequence 1 (continued):
1320 // The first context lost happens before the resources were created,
1321 // and because it resulted in no resources being destroyed, it does not
1322 // trigger resource re-creation.
1323 EXPECT_EQ(1, ui_resource_->resource_create_count);
1324 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1325 // Resource Id on the impl-side has been created.
1326 PostSetNeedsCommitToMainThread();
1327 break;
1328 case 3:
1329 // Sequence 2 (continued):
1330 // The previous resource should have been deleted.
1331 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1332 // The second resource should have been created.
1333 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
1334 // The second resource called the resource callback once and since the
1335 // context is lost, a "resource lost" callback was also issued.
1336 EXPECT_EQ(2, ui_resource_->resource_create_count);
1337 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1338 break;
1339 case 5:
1340 // Sequence 3 (continued):
1341 // Expect the resource callback to have been called once.
1342 EXPECT_EQ(1, ui_resource_->resource_create_count);
1343 // No "resource lost" callbacks.
1344 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1345 // The UI resource id should not be valid
1346 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1347 break;
1351 private:
1352 UIResourceId test_id0_;
1353 UIResourceId test_id1_;
1356 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
1358 // Losing UI resource before the pending trees is activated but after the
1359 // commit. Impl-side-painting only.
1360 class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
1361 void StepCompleteOnMainThread(int step) override {
1362 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1363 switch (step) {
1364 case 0:
1365 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1366 PostSetNeedsCommitToMainThread();
1367 break;
1368 case 3:
1369 test_id_ = ui_resource_->id();
1370 ui_resource_ = nullptr;
1371 PostSetNeedsCommitToMainThread();
1372 break;
1373 case 5:
1374 // Release resource before ending the test.
1375 ui_resource_ = nullptr;
1376 EndTest();
1377 break;
1378 case 6:
1379 // Make sure no extra commits happened.
1380 NOTREACHED();
1384 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
1385 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1386 switch (time_step_) {
1387 case 2:
1388 PostSetNeedsCommitToMainThread();
1389 break;
1390 case 4:
1391 PostSetNeedsCommitToMainThread();
1392 break;
1396 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
1397 switch (time_step_) {
1398 case 1:
1399 // The resource creation callback has been called.
1400 EXPECT_EQ(1, ui_resource_->resource_create_count);
1401 // The resource is not yet lost (sanity check).
1402 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1403 // The resource should not have been created yet on the impl-side.
1404 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1405 LoseContext();
1406 break;
1407 case 3:
1408 LoseContext();
1409 break;
1413 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
1414 LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1415 switch (time_step_) {
1416 case 1:
1417 // The pending requests on the impl-side should have been processed.
1418 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1419 break;
1420 case 2:
1421 // The "lost resource" callback should have been called once.
1422 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1423 break;
1424 case 4:
1425 // The resource is deleted and should not be in the manager. Use
1426 // test_id_ since ui_resource_ has been deleted.
1427 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
1428 break;
1431 PostStepCompleteToMainThread();
1432 ++time_step_;
1435 private:
1436 UIResourceId test_id_;
1439 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeActivateTree);
1441 // Resources evicted explicitly and by visibility changes.
1442 class UIResourceLostEviction : public UIResourceLostTestSimple {
1443 public:
1444 void StepCompleteOnMainThread(int step) override {
1445 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1446 switch (step) {
1447 case 0:
1448 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1449 EXPECT_NE(0, ui_resource_->id());
1450 PostSetNeedsCommitToMainThread();
1451 break;
1452 case 2:
1453 // Make the tree not visible.
1454 PostSetVisibleToMainThread(false);
1455 break;
1456 case 3:
1457 // Release resource before ending the test.
1458 ui_resource_ = nullptr;
1459 EndTest();
1460 break;
1461 case 4:
1462 NOTREACHED();
1466 void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl, bool visible) override {
1467 TestWebGraphicsContext3D* context = TestContext();
1468 if (!visible) {
1469 // All resources should have been evicted.
1470 ASSERT_EQ(0u, context->NumTextures());
1471 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1472 EXPECT_EQ(2, ui_resource_->resource_create_count);
1473 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1474 // Drawing is disabled both because of the evicted resources and
1475 // because the renderer is not visible.
1476 EXPECT_FALSE(impl->CanDraw());
1477 // Make the renderer visible again.
1478 PostSetVisibleToMainThread(true);
1482 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
1483 TestWebGraphicsContext3D* context = TestContext();
1484 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1485 switch (time_step_) {
1486 case 1:
1487 // The resource should have been created on LTHI after the commit.
1488 ASSERT_EQ(1u, context->NumTextures());
1489 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1490 EXPECT_EQ(1, ui_resource_->resource_create_count);
1491 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1492 EXPECT_TRUE(impl->CanDraw());
1493 // Evict all UI resources. This will trigger a commit.
1494 impl->EvictAllUIResources();
1495 ASSERT_EQ(0u, context->NumTextures());
1496 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1497 EXPECT_EQ(1, ui_resource_->resource_create_count);
1498 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1499 EXPECT_FALSE(impl->CanDraw());
1500 break;
1501 case 2:
1502 // The resource should have been recreated.
1503 ASSERT_EQ(1u, context->NumTextures());
1504 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1505 EXPECT_EQ(2, ui_resource_->resource_create_count);
1506 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1507 EXPECT_TRUE(impl->CanDraw());
1508 break;
1509 case 3:
1510 // The resource should have been recreated after visibility was
1511 // restored.
1512 ASSERT_EQ(1u, context->NumTextures());
1513 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1514 EXPECT_EQ(3, ui_resource_->resource_create_count);
1515 EXPECT_EQ(2, ui_resource_->lost_resource_count);
1516 EXPECT_TRUE(impl->CanDraw());
1517 break;
1522 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1524 class LayerTreeHostContextTestSurfaceCreateCallback
1525 : public LayerTreeHostContextTest {
1526 public:
1527 LayerTreeHostContextTestSurfaceCreateCallback()
1528 : LayerTreeHostContextTest() {}
1530 void SetupTree() override {
1531 picture_layer_ = FakePictureLayer::Create(layer_settings(), &client_);
1532 picture_layer_->SetBounds(gfx::Size(10, 20));
1533 layer_tree_host()->SetRootLayer(picture_layer_);
1535 LayerTreeHostContextTest::SetupTree();
1538 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1540 void DidCommit() override {
1541 switch (layer_tree_host()->source_frame_number()) {
1542 case 1:
1543 EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
1544 layer_tree_host()->SetNeedsCommit();
1545 break;
1546 case 2:
1547 EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
1548 layer_tree_host()->SetNeedsCommit();
1549 break;
1550 case 3:
1551 EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
1552 break;
1553 case 4:
1554 EXPECT_EQ(2u, picture_layer_->output_surface_created_count());
1555 layer_tree_host()->SetNeedsCommit();
1556 break;
1560 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
1561 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1562 switch (LastCommittedSourceFrameNumber(impl)) {
1563 case 0:
1564 break;
1565 case 1:
1566 break;
1567 case 2:
1568 LoseContext();
1569 break;
1570 case 3:
1571 EndTest();
1572 break;
1576 void AfterTest() override {}
1578 protected:
1579 FakeContentLayerClient client_;
1580 scoped_refptr<FakePictureLayer> picture_layer_;
1583 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
1585 class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
1586 : public LayerTreeHostContextTest {
1587 protected:
1588 void BeginTest() override {
1589 deferred_ = false;
1590 PostSetNeedsCommitToMainThread();
1593 void ScheduledActionWillSendBeginMainFrame() override {
1594 if (deferred_)
1595 return;
1596 deferred_ = true;
1598 // Defer commits before the BeginFrame arrives, causing it to be delayed.
1599 PostSetDeferCommitsToMainThread(true);
1600 // Meanwhile, lose the context while we are in defer commits.
1601 ImplThreadTaskRunner()->PostTask(
1602 FROM_HERE,
1603 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1604 LoseContextOnImplThread,
1605 base::Unretained(this)));
1608 void LoseContextOnImplThread() {
1609 LoseContext();
1611 // After losing the context, stop deferring commits.
1612 PostSetDeferCommitsToMainThread(false);
1615 void WillBeginMainFrame() override {
1616 // Don't begin a frame with a lost surface.
1617 EXPECT_FALSE(layer_tree_host()->output_surface_lost());
1620 void DidCommitAndDrawFrame() override { EndTest(); }
1622 void AfterTest() override {}
1624 bool deferred_;
1627 SINGLE_AND_MULTI_THREAD_TEST_F(
1628 LayerTreeHostContextTestLoseAfterSendingBeginMainFrame);
1630 } // namespace
1631 } // namespace cc