Getting rid of GetDefaultProfile(), clean up of ProfileManager (which was in a seriou...
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_context.cc
blobb53127d4d9e09f4fabc70613478c228740de9088
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host.h"
7 #include "base/basictypes.h"
8 #include "cc/layers/content_layer.h"
9 #include "cc/layers/delegated_frame_provider.h"
10 #include "cc/layers/delegated_frame_resource_collection.h"
11 #include "cc/layers/heads_up_display_layer.h"
12 #include "cc/layers/io_surface_layer.h"
13 #include "cc/layers/layer_impl.h"
14 #include "cc/layers/painted_scrollbar_layer.h"
15 #include "cc/layers/picture_layer.h"
16 #include "cc/layers/texture_layer.h"
17 #include "cc/layers/texture_layer_impl.h"
18 #include "cc/layers/video_layer.h"
19 #include "cc/layers/video_layer_impl.h"
20 #include "cc/output/filter_operations.h"
21 #include "cc/test/fake_content_layer.h"
22 #include "cc/test/fake_content_layer_client.h"
23 #include "cc/test/fake_content_layer_impl.h"
24 #include "cc/test/fake_delegated_renderer_layer.h"
25 #include "cc/test/fake_delegated_renderer_layer_impl.h"
26 #include "cc/test/fake_layer_tree_host_client.h"
27 #include "cc/test/fake_output_surface.h"
28 #include "cc/test/fake_output_surface_client.h"
29 #include "cc/test/fake_painted_scrollbar_layer.h"
30 #include "cc/test/fake_scoped_ui_resource.h"
31 #include "cc/test/fake_scrollbar.h"
32 #include "cc/test/fake_video_frame_provider.h"
33 #include "cc/test/layer_tree_test.h"
34 #include "cc/test/render_pass_test_common.h"
35 #include "cc/test/test_context_provider.h"
36 #include "cc/test/test_web_graphics_context_3d.h"
37 #include "cc/trees/layer_tree_host_impl.h"
38 #include "cc/trees/layer_tree_impl.h"
39 #include "cc/trees/single_thread_proxy.h"
40 #include "gpu/GLES2/gl2extchromium.h"
41 #include "media/base/media.h"
43 using media::VideoFrame;
45 namespace cc {
46 namespace {
48 // These tests deal with losing the 3d graphics context.
49 class LayerTreeHostContextTest : public LayerTreeTest {
50 public:
51 LayerTreeHostContextTest()
52 : LayerTreeTest(),
53 context3d_(NULL),
54 times_to_fail_create_(0),
55 times_to_lose_during_commit_(0),
56 times_to_lose_during_draw_(0),
57 times_to_fail_recreate_(0),
58 times_to_fail_create_offscreen_(0),
59 times_to_fail_recreate_offscreen_(0),
60 times_to_expect_create_failed_(0),
61 times_create_failed_(0),
62 times_offscreen_created_(0),
63 committed_at_least_once_(false),
64 context_should_support_io_surface_(false),
65 fallback_context_works_(false) {
66 media::InitializeMediaLibraryForTesting();
69 void LoseContext() {
70 context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
71 GL_INNOCENT_CONTEXT_RESET_ARB);
72 context3d_ = NULL;
75 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
76 return TestWebGraphicsContext3D::Create();
79 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
80 OVERRIDE {
81 if (times_to_fail_create_) {
82 --times_to_fail_create_;
83 ExpectCreateToFail();
84 return scoped_ptr<OutputSurface>();
87 scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
88 context3d_ = context3d.get();
90 if (context_should_support_io_surface_) {
91 context3d_->set_have_extension_io_surface(true);
92 context3d_->set_have_extension_egl_image(true);
95 if (delegating_renderer()) {
96 return FakeOutputSurface::CreateDelegating3d(context3d.Pass())
97 .PassAs<OutputSurface>();
99 return FakeOutputSurface::Create3d(context3d.Pass())
100 .PassAs<OutputSurface>();
103 scoped_ptr<TestWebGraphicsContext3D> CreateOffscreenContext3d() {
104 if (!context3d_)
105 return scoped_ptr<TestWebGraphicsContext3D>();
107 ++times_offscreen_created_;
109 if (times_to_fail_create_offscreen_) {
110 --times_to_fail_create_offscreen_;
111 ExpectCreateToFail();
112 return scoped_ptr<TestWebGraphicsContext3D>();
115 scoped_ptr<TestWebGraphicsContext3D> offscreen_context3d =
116 TestWebGraphicsContext3D::Create().Pass();
117 DCHECK(offscreen_context3d);
118 context3d_->add_share_group_context(offscreen_context3d.get());
120 return offscreen_context3d.Pass();
123 virtual scoped_refptr<ContextProvider> OffscreenContextProvider() OVERRIDE {
124 if (!offscreen_contexts_.get() ||
125 offscreen_contexts_->DestroyedOnMainThread()) {
126 offscreen_contexts_ =
127 TestContextProvider::Create(CreateOffscreenContext3d());
129 return offscreen_contexts_;
132 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
133 LayerTreeHostImpl::FrameData* frame,
134 bool result) OVERRIDE {
135 EXPECT_TRUE(result);
136 if (!times_to_lose_during_draw_)
137 return result;
139 --times_to_lose_during_draw_;
140 LoseContext();
142 times_to_fail_create_ = times_to_fail_recreate_;
143 times_to_fail_recreate_ = 0;
144 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
145 times_to_fail_recreate_offscreen_ = 0;
147 return result;
150 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
151 committed_at_least_once_ = true;
153 if (!times_to_lose_during_commit_)
154 return;
155 --times_to_lose_during_commit_;
156 LoseContext();
158 times_to_fail_create_ = times_to_fail_recreate_;
159 times_to_fail_recreate_ = 0;
160 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
161 times_to_fail_recreate_offscreen_ = 0;
164 virtual void DidFailToInitializeOutputSurface() OVERRIDE {
165 ++times_create_failed_;
168 virtual void TearDown() OVERRIDE {
169 LayerTreeTest::TearDown();
170 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
173 void ExpectCreateToFail() {
174 ++times_to_expect_create_failed_;
177 protected:
178 TestWebGraphicsContext3D* context3d_;
179 int times_to_fail_create_;
180 int times_to_lose_during_commit_;
181 int times_to_lose_during_draw_;
182 int times_to_fail_recreate_;
183 int times_to_fail_create_offscreen_;
184 int times_to_fail_recreate_offscreen_;
185 int times_to_expect_create_failed_;
186 int times_create_failed_;
187 int times_offscreen_created_;
188 bool committed_at_least_once_;
189 bool context_should_support_io_surface_;
190 bool fallback_context_works_;
192 scoped_refptr<TestContextProvider> offscreen_contexts_;
195 class LayerTreeHostContextTestLostContextSucceeds
196 : public LayerTreeHostContextTest {
197 public:
198 LayerTreeHostContextTestLostContextSucceeds()
199 : LayerTreeHostContextTest(),
200 test_case_(0),
201 num_losses_(0),
202 num_losses_last_test_case_(-1),
203 recovered_context_(true),
204 first_initialized_(false) {}
206 virtual void BeginTest() OVERRIDE {
207 PostSetNeedsCommitToMainThread();
210 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
211 EXPECT_TRUE(succeeded);
213 if (first_initialized_)
214 ++num_losses_;
215 else
216 first_initialized_ = true;
218 recovered_context_ = true;
221 virtual void AfterTest() OVERRIDE { EXPECT_EQ(9u, test_case_); }
223 virtual void DidCommitAndDrawFrame() OVERRIDE {
224 // If the last frame had a context loss, then we'll commit again to
225 // recover.
226 if (!recovered_context_)
227 return;
228 if (times_to_lose_during_commit_)
229 return;
230 if (times_to_lose_during_draw_)
231 return;
233 recovered_context_ = false;
234 if (NextTestCase())
235 InvalidateAndSetNeedsCommit();
236 else
237 EndTest();
240 virtual void InvalidateAndSetNeedsCommit() {
241 // Cause damage so we try to draw.
242 layer_tree_host()->root_layer()->SetNeedsDisplay();
243 layer_tree_host()->SetNeedsCommit();
246 bool NextTestCase() {
247 static const TestCase kTests[] = {
248 // Losing the context and failing to recreate it (or losing it again
249 // immediately) a small number of times should succeed.
250 { 1, // times_to_lose_during_commit
251 0, // times_to_lose_during_draw
252 0, // times_to_fail_recreate
253 0, // times_to_fail_recreate_offscreen
254 false, // fallback_context_works
256 { 0, // times_to_lose_during_commit
257 1, // times_to_lose_during_draw
258 0, // times_to_fail_recreate
259 0, // times_to_fail_recreate_offscreen
260 false, // fallback_context_works
262 { 1, // times_to_lose_during_commit
263 0, // times_to_lose_during_draw
264 3, // times_to_fail_recreate
265 0, // times_to_fail_recreate_offscreen
266 false, // fallback_context_works
268 { 0, // times_to_lose_during_commit
269 1, // times_to_lose_during_draw
270 3, // times_to_fail_recreate
271 0, // times_to_fail_recreate_offscreen
272 false, // fallback_context_works
274 { 1, // times_to_lose_during_commit
275 0, // times_to_lose_during_draw
276 0, // times_to_fail_recreate
277 3, // times_to_fail_recreate_offscreen
278 false, // fallback_context_works
280 { 0, // times_to_lose_during_commit
281 1, // times_to_lose_during_draw
282 0, // times_to_fail_recreate
283 3, // times_to_fail_recreate_offscreen
284 false, // fallback_context_works
286 // Losing the context and recreating it any number of times should
287 // succeed.
288 { 10, // times_to_lose_during_commit
289 0, // times_to_lose_during_draw
290 0, // times_to_fail_recreate
291 0, // times_to_fail_recreate_offscreen
292 false, // fallback_context_works
294 { 0, // times_to_lose_during_commit
295 10, // times_to_lose_during_draw
296 0, // times_to_fail_recreate
297 0, // times_to_fail_recreate_offscreen
298 false, // fallback_context_works
300 // Losing the context, failing to reinitialize it, and making a fallback
301 // context should work.
302 { 0, // times_to_lose_during_commit
303 1, // times_to_lose_during_draw
304 0, // times_to_fail_recreate
305 0, // times_to_fail_recreate_offscreen
306 true, // fallback_context_works
310 if (test_case_ >= arraysize(kTests))
311 return false;
312 // Make sure that we lost our context at least once in the last test run so
313 // the test did something.
314 EXPECT_GT(num_losses_, num_losses_last_test_case_);
315 num_losses_last_test_case_ = num_losses_;
317 times_to_lose_during_commit_ =
318 kTests[test_case_].times_to_lose_during_commit;
319 times_to_lose_during_draw_ =
320 kTests[test_case_].times_to_lose_during_draw;
321 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
322 times_to_fail_recreate_offscreen_ =
323 kTests[test_case_].times_to_fail_recreate_offscreen;
324 fallback_context_works_ = kTests[test_case_].fallback_context_works;
325 ++test_case_;
326 return true;
329 struct TestCase {
330 int times_to_lose_during_commit;
331 int times_to_lose_during_draw;
332 int times_to_fail_recreate;
333 int times_to_fail_recreate_offscreen;
334 bool fallback_context_works;
337 protected:
338 size_t test_case_;
339 int num_losses_;
340 int num_losses_last_test_case_;
341 bool recovered_context_;
342 bool first_initialized_;
345 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
347 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
348 : public LayerTreeHostContextTest {
349 public:
350 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
351 : LayerTreeHostContextTest() {}
353 virtual void WillBeginTest() OVERRIDE {
354 // Override and do not signal SetLayerTreeHostClientReady.
357 virtual void BeginTest() OVERRIDE {
358 PostSetNeedsCommitToMainThread();
359 EndTest();
362 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
363 OVERRIDE {
364 EXPECT_TRUE(false);
365 return scoped_ptr<OutputSurface>();
368 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
369 EXPECT_TRUE(false);
372 virtual void AfterTest() OVERRIDE {
376 MULTI_THREAD_TEST_F(LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
378 class LayerTreeHostContextTestLostContextSucceedsWithContent
379 : public LayerTreeHostContextTestLostContextSucceeds {
380 public:
381 LayerTreeHostContextTestLostContextSucceedsWithContent()
382 : LayerTreeHostContextTestLostContextSucceeds() {}
384 virtual void SetupTree() OVERRIDE {
385 root_ = Layer::Create();
386 root_->SetBounds(gfx::Size(10, 10));
387 root_->SetAnchorPoint(gfx::PointF());
388 root_->SetIsDrawable(true);
390 content_ = FakeContentLayer::Create(&client_);
391 content_->SetBounds(gfx::Size(10, 10));
392 content_->SetAnchorPoint(gfx::PointF());
393 content_->SetIsDrawable(true);
394 if (use_surface_) {
395 content_->SetForceRenderSurface(true);
396 // Filters require us to create an offscreen context.
397 FilterOperations filters;
398 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
399 content_->SetFilters(filters);
400 content_->SetBackgroundFilters(filters);
403 root_->AddChild(content_);
405 layer_tree_host()->SetRootLayer(root_);
406 LayerTreeHostContextTest::SetupTree();
409 virtual void InvalidateAndSetNeedsCommit() OVERRIDE {
410 // Invalidate the render surface so we don't try to use a cached copy of the
411 // surface. We want to make sure to test the drawing paths for drawing to
412 // a child surface.
413 content_->SetNeedsDisplay();
414 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
417 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
418 FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>(
419 host_impl->active_tree()->root_layer()->children()[0]);
420 // Even though the context was lost, we should have a resource. The
421 // TestWebGraphicsContext3D ensures that this resource is created with
422 // the active context.
423 EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
425 ContextProvider* contexts = host_impl->offscreen_context_provider();
426 if (use_surface_) {
427 ASSERT_TRUE(contexts);
428 EXPECT_TRUE(contexts->ContextGL());
429 // TODO(danakj): Make a fake GrContext.
430 // EXPECT_TRUE(contexts->GrContext());
431 } else {
432 EXPECT_FALSE(contexts);
436 virtual void AfterTest() OVERRIDE {
437 LayerTreeHostContextTestLostContextSucceeds::AfterTest();
438 if (use_surface_) {
439 // 1 create to start with +
440 // 4 from test cases that lose the offscreen context directly +
441 // 2 from test cases that create a fallback +
442 // All the test cases that recreate both contexts only once
443 // per time it is lost.
444 EXPECT_EQ(4 + 1 + 2 + num_losses_, times_offscreen_created_);
445 } else {
446 EXPECT_EQ(0, times_offscreen_created_);
450 protected:
451 bool use_surface_;
452 FakeContentLayerClient client_;
453 scoped_refptr<Layer> root_;
454 scoped_refptr<ContentLayer> content_;
457 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
458 NoSurface_SingleThread_DirectRenderer) {
459 use_surface_ = false;
460 RunTest(false, false, false);
463 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
464 NoSurface_SingleThread_DelegatingRenderer) {
465 use_surface_ = false;
466 RunTest(false, true, false);
469 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
470 NoSurface_MultiThread_DirectRenderer_MainThreadPaint) {
471 use_surface_ = false;
472 RunTest(true, false, false);
475 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
476 NoSurface_MultiThread_DelegatingRenderer_MainThreadPaint) {
477 use_surface_ = false;
478 RunTest(true, true, false);
481 // Surfaces don't exist with a delegating renderer.
482 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
483 WithSurface_SingleThread_DirectRenderer) {
484 use_surface_ = true;
485 RunTest(false, false, false);
488 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
489 WithSurface_MultiThread_DirectRenderer_MainThreadPaint) {
490 use_surface_ = true;
491 RunTest(true, false, false);
494 class LayerTreeHostContextTestCreateOutputSurfaceFails
495 : public LayerTreeHostContextTest {
496 public:
497 // Run a test that initially fails OutputSurface creation |times_to_fail|
498 // times. If |expect_fallback_attempt| is |true|, an attempt to create a
499 // fallback/software OutputSurface is expected to occur.
500 LayerTreeHostContextTestCreateOutputSurfaceFails(int times_to_fail,
501 bool expect_fallback_attempt,
502 bool expect_to_give_up)
503 : times_to_fail_(times_to_fail),
504 expect_fallback_attempt_(expect_fallback_attempt),
505 expect_to_give_up_(expect_to_give_up),
506 did_attempt_fallback_(false),
507 times_initialized_(0) {}
509 virtual void BeginTest() OVERRIDE {
510 times_to_fail_create_ = times_to_fail_;
511 PostSetNeedsCommitToMainThread();
514 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
515 OVERRIDE {
516 scoped_ptr<OutputSurface> surface =
517 LayerTreeHostContextTest::CreateOutputSurface(fallback);
519 if (surface)
520 EXPECT_EQ(times_to_fail_, times_create_failed_);
522 did_attempt_fallback_ = fallback;
523 return surface.Pass();
526 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
527 if (succeeded)
528 times_initialized_++;
529 else
530 EndTest();
533 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
534 EndTest();
537 virtual void AfterTest() OVERRIDE {
538 EXPECT_EQ(times_to_fail_, times_create_failed_);
539 EXPECT_EQ(expect_to_give_up_, times_initialized_ == 0);
540 EXPECT_EQ(expect_fallback_attempt_, did_attempt_fallback_);
543 private:
544 int times_to_fail_;
545 bool expect_fallback_attempt_;
546 bool expect_to_give_up_;
547 bool did_attempt_fallback_;
548 int times_initialized_;
551 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
552 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
553 public:
554 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
555 : LayerTreeHostContextTestCreateOutputSurfaceFails(1, false, false) {}
558 SINGLE_AND_MULTI_THREAD_TEST_F(
559 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce);
561 // After 4 failures we expect an attempt to create a fallback/software
562 // OutputSurface.
563 class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
564 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
565 public:
566 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback()
567 : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true, false) {}
570 SINGLE_AND_MULTI_THREAD_TEST_F(
571 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback);
573 // If we fail that often, we should be giving up cleanly.
574 class LayerTreeHostContextTestCreateOutputSurfaceIsHopeless
575 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
576 public:
577 LayerTreeHostContextTestCreateOutputSurfaceIsHopeless()
578 : LayerTreeHostContextTestCreateOutputSurfaceFails(5, true, true) {}
581 SINGLE_AND_MULTI_THREAD_TEST_F(
582 LayerTreeHostContextTestCreateOutputSurfaceIsHopeless);
585 class LayerTreeHostContextTestOffscreenContextFails
586 : public LayerTreeHostContextTest {
587 public:
588 virtual void SetupTree() OVERRIDE {
589 root_ = Layer::Create();
590 root_->SetBounds(gfx::Size(10, 10));
591 root_->SetAnchorPoint(gfx::PointF());
592 root_->SetIsDrawable(true);
594 content_ = FakeContentLayer::Create(&client_);
595 content_->SetBounds(gfx::Size(10, 10));
596 content_->SetAnchorPoint(gfx::PointF());
597 content_->SetIsDrawable(true);
598 content_->SetForceRenderSurface(true);
599 // Filters require us to create an offscreen context.
600 FilterOperations filters;
601 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
602 content_->SetFilters(filters);
603 content_->SetBackgroundFilters(filters);
605 root_->AddChild(content_);
607 layer_tree_host()->SetRootLayer(root_);
608 LayerTreeHostContextTest::SetupTree();
611 virtual void BeginTest() OVERRIDE {
612 times_to_fail_create_offscreen_ = 1;
613 PostSetNeedsCommitToMainThread();
616 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
617 ContextProvider* contexts = host_impl->offscreen_context_provider();
618 EXPECT_FALSE(contexts);
620 // This did not lead to create failure.
621 times_to_expect_create_failed_ = 0;
622 EndTest();
625 virtual void AfterTest() OVERRIDE {}
627 protected:
628 FakeContentLayerClient client_;
629 scoped_refptr<Layer> root_;
630 scoped_refptr<ContentLayer> content_;
633 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestOffscreenContextFails);
635 class LayerTreeHostContextTestLostContextFails
636 : public LayerTreeHostContextTest {
637 public:
638 LayerTreeHostContextTestLostContextFails()
639 : LayerTreeHostContextTest(),
640 num_commits_(0),
641 first_initialized_(false) {
642 times_to_lose_during_commit_ = 1;
645 virtual void BeginTest() OVERRIDE {
646 PostSetNeedsCommitToMainThread();
649 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
650 if (first_initialized_) {
651 EXPECT_FALSE(succeeded);
652 EndTest();
653 } else {
654 first_initialized_ = true;
658 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
659 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
661 ++num_commits_;
662 if (num_commits_ == 1) {
663 // When the context is ok, we should have these things.
664 EXPECT_TRUE(host_impl->output_surface());
665 EXPECT_TRUE(host_impl->renderer());
666 EXPECT_TRUE(host_impl->resource_provider());
667 return;
670 // When context recreation fails we shouldn't be left with any of them.
671 EXPECT_FALSE(host_impl->output_surface());
672 EXPECT_FALSE(host_impl->renderer());
673 EXPECT_FALSE(host_impl->resource_provider());
676 virtual void AfterTest() OVERRIDE {}
678 private:
679 int num_commits_;
680 bool first_initialized_;
683 class LayerTreeHostContextTestLostContextAndEvictTextures
684 : public LayerTreeHostContextTest {
685 public:
686 LayerTreeHostContextTestLostContextAndEvictTextures()
687 : LayerTreeHostContextTest(),
688 layer_(FakeContentLayer::Create(&client_)),
689 impl_host_(0),
690 num_commits_(0) {}
692 virtual void SetupTree() OVERRIDE {
693 layer_->SetBounds(gfx::Size(10, 20));
694 layer_tree_host()->SetRootLayer(layer_);
695 LayerTreeHostContextTest::SetupTree();
698 virtual void BeginTest() OVERRIDE {
699 PostSetNeedsCommitToMainThread();
702 void PostEvictTextures() {
703 if (HasImplThread()) {
704 ImplThreadTaskRunner()->PostTask(
705 FROM_HERE,
706 base::Bind(
707 &LayerTreeHostContextTestLostContextAndEvictTextures::
708 EvictTexturesOnImplThread,
709 base::Unretained(this)));
710 } else {
711 DebugScopedSetImplThread impl(proxy());
712 EvictTexturesOnImplThread();
716 void EvictTexturesOnImplThread() {
717 impl_host_->EvictTexturesForTesting();
718 if (lose_after_evict_)
719 LoseContext();
722 virtual void DidCommitAndDrawFrame() OVERRIDE {
723 if (num_commits_ > 1)
724 return;
725 EXPECT_TRUE(layer_->HaveBackingAt(0, 0));
726 PostEvictTextures();
729 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
730 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
731 if (num_commits_ > 1)
732 return;
733 ++num_commits_;
734 if (!lose_after_evict_)
735 LoseContext();
736 impl_host_ = impl;
739 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
740 EXPECT_TRUE(succeeded);
741 EndTest();
744 virtual void AfterTest() OVERRIDE {}
746 protected:
747 bool lose_after_evict_;
748 FakeContentLayerClient client_;
749 scoped_refptr<FakeContentLayer> layer_;
750 LayerTreeHostImpl* impl_host_;
751 int num_commits_;
754 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
755 LoseAfterEvict_SingleThread_DirectRenderer) {
756 lose_after_evict_ = true;
757 RunTest(false, false, false);
760 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
761 LoseAfterEvict_SingleThread_DelegatingRenderer) {
762 lose_after_evict_ = true;
763 RunTest(false, true, false);
766 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
767 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) {
768 lose_after_evict_ = true;
769 RunTest(true, false, false);
772 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
773 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
774 lose_after_evict_ = true;
775 RunTest(true, true, false);
778 // Flaky on all platforms, http://crbug.com/310979
779 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
780 DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
781 lose_after_evict_ = true;
782 RunTest(true, true, true);
785 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
786 LoseBeforeEvict_SingleThread_DirectRenderer) {
787 lose_after_evict_ = false;
788 RunTest(false, false, false);
791 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
792 LoseBeforeEvict_SingleThread_DelegatingRenderer) {
793 lose_after_evict_ = false;
794 RunTest(false, true, false);
797 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
798 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) {
799 lose_after_evict_ = false;
800 RunTest(true, false, false);
803 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
804 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) {
805 lose_after_evict_ = false;
806 RunTest(true, false, true);
809 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
810 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
811 lose_after_evict_ = false;
812 RunTest(true, true, false);
815 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
816 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
817 lose_after_evict_ = false;
818 RunTest(true, true, true);
821 class LayerTreeHostContextTestLostContextWhileUpdatingResources
822 : public LayerTreeHostContextTest {
823 public:
824 LayerTreeHostContextTestLostContextWhileUpdatingResources()
825 : parent_(FakeContentLayer::Create(&client_)),
826 num_children_(50),
827 times_to_lose_on_end_query_(3) {}
829 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() OVERRIDE {
830 scoped_ptr<TestWebGraphicsContext3D> context =
831 LayerTreeHostContextTest::CreateContext3d();
832 if (times_to_lose_on_end_query_) {
833 --times_to_lose_on_end_query_;
834 context->set_times_end_query_succeeds(5);
836 return context.Pass();
839 virtual void SetupTree() OVERRIDE {
840 parent_->SetBounds(gfx::Size(num_children_, 1));
842 for (int i = 0; i < num_children_; i++) {
843 scoped_refptr<FakeContentLayer> child =
844 FakeContentLayer::Create(&client_);
845 child->SetPosition(gfx::PointF(i, 0.f));
846 child->SetBounds(gfx::Size(1, 1));
847 parent_->AddChild(child);
850 layer_tree_host()->SetRootLayer(parent_);
851 LayerTreeHostContextTest::SetupTree();
854 virtual void BeginTest() OVERRIDE {
855 PostSetNeedsCommitToMainThread();
858 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
859 EXPECT_EQ(0, times_to_lose_on_end_query_);
860 EndTest();
863 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
864 EXPECT_TRUE(succeeded);
867 virtual void AfterTest() OVERRIDE {
868 EXPECT_EQ(0, times_to_lose_on_end_query_);
871 private:
872 FakeContentLayerClient client_;
873 scoped_refptr<FakeContentLayer> parent_;
874 int num_children_;
875 int times_to_lose_on_end_query_;
878 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
879 LayerTreeHostContextTestLostContextWhileUpdatingResources);
881 class LayerTreeHostContextTestLayersNotified
882 : public LayerTreeHostContextTest {
883 public:
884 LayerTreeHostContextTestLayersNotified()
885 : LayerTreeHostContextTest(),
886 num_commits_(0) {}
888 virtual void SetupTree() OVERRIDE {
889 root_ = FakeContentLayer::Create(&client_);
890 child_ = FakeContentLayer::Create(&client_);
891 grandchild_ = FakeContentLayer::Create(&client_);
893 root_->AddChild(child_);
894 child_->AddChild(grandchild_);
896 layer_tree_host()->SetRootLayer(root_);
897 LayerTreeHostContextTest::SetupTree();
900 virtual void BeginTest() OVERRIDE {
901 PostSetNeedsCommitToMainThread();
904 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
905 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
907 FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>(
908 host_impl->active_tree()->root_layer());
909 FakeContentLayerImpl* child = static_cast<FakeContentLayerImpl*>(
910 root->children()[0]);
911 FakeContentLayerImpl* grandchild = static_cast<FakeContentLayerImpl*>(
912 child->children()[0]);
914 ++num_commits_;
915 switch (num_commits_) {
916 case 1:
917 EXPECT_EQ(0u, root->lost_output_surface_count());
918 EXPECT_EQ(0u, child->lost_output_surface_count());
919 EXPECT_EQ(0u, grandchild->lost_output_surface_count());
920 // Lose the context and struggle to recreate it.
921 LoseContext();
922 times_to_fail_create_ = 1;
923 break;
924 case 2:
925 EXPECT_GE(1u, root->lost_output_surface_count());
926 EXPECT_GE(1u, child->lost_output_surface_count());
927 EXPECT_GE(1u, grandchild->lost_output_surface_count());
928 EndTest();
929 break;
930 default:
931 NOTREACHED();
935 virtual void AfterTest() OVERRIDE {}
937 private:
938 int num_commits_;
940 FakeContentLayerClient client_;
941 scoped_refptr<FakeContentLayer> root_;
942 scoped_refptr<FakeContentLayer> child_;
943 scoped_refptr<FakeContentLayer> grandchild_;
946 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
948 class LayerTreeHostContextTestDontUseLostResources
949 : public LayerTreeHostContextTest {
950 public:
951 LayerTreeHostContextTestDontUseLostResources()
952 : lost_context_(false) {
953 context_should_support_io_surface_ = true;
955 child_output_surface_ = FakeOutputSurface::Create3d();
956 child_output_surface_->BindToClient(&output_surface_client_);
957 child_resource_provider_ =
958 ResourceProvider::Create(child_output_surface_.get(),
959 NULL,
961 false,
965 static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
967 virtual void SetupTree() OVERRIDE {
968 gpu::gles2::GLES2Interface* gl =
969 child_output_surface_->context_provider()->ContextGL();
971 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
973 scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
974 pass_for_quad->SetNew(
975 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
976 RenderPass::Id(2, 1),
977 gfx::Rect(0, 0, 10, 10),
978 gfx::Rect(0, 0, 10, 10),
979 gfx::Transform());
981 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
982 pass->SetNew(RenderPass::Id(1, 1),
983 gfx::Rect(0, 0, 10, 10),
984 gfx::Rect(0, 0, 10, 10),
985 gfx::Transform());
986 pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
987 RenderPass::Id(2, 1));
989 frame_data->render_pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
990 frame_data->render_pass_list.push_back(pass.PassAs<RenderPass>());
992 delegated_resource_collection_ = new DelegatedFrameResourceCollection;
993 delegated_frame_provider_ = new DelegatedFrameProvider(
994 delegated_resource_collection_.get(), frame_data.Pass());
996 ResourceProvider::ResourceId resource =
997 child_resource_provider_->CreateResource(
998 gfx::Size(4, 4),
999 GL_CLAMP_TO_EDGE,
1000 ResourceProvider::TextureUsageAny,
1001 RGBA_8888);
1002 ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
1003 resource);
1005 gpu::Mailbox mailbox;
1006 gl->GenMailboxCHROMIUM(mailbox.name);
1007 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1009 scoped_refptr<Layer> root = Layer::Create();
1010 root->SetBounds(gfx::Size(10, 10));
1011 root->SetAnchorPoint(gfx::PointF());
1012 root->SetIsDrawable(true);
1014 scoped_refptr<FakeDelegatedRendererLayer> delegated =
1015 FakeDelegatedRendererLayer::Create(delegated_frame_provider_.get());
1016 delegated->SetBounds(gfx::Size(10, 10));
1017 delegated->SetAnchorPoint(gfx::PointF());
1018 delegated->SetIsDrawable(true);
1019 root->AddChild(delegated);
1021 scoped_refptr<ContentLayer> content = ContentLayer::Create(&client_);
1022 content->SetBounds(gfx::Size(10, 10));
1023 content->SetAnchorPoint(gfx::PointF());
1024 content->SetIsDrawable(true);
1025 root->AddChild(content);
1027 scoped_refptr<TextureLayer> texture = TextureLayer::CreateForMailbox(NULL);
1028 texture->SetBounds(gfx::Size(10, 10));
1029 texture->SetAnchorPoint(gfx::PointF());
1030 texture->SetIsDrawable(true);
1031 texture->SetTextureMailbox(
1032 TextureMailbox(mailbox, sync_point),
1033 SingleReleaseCallback::Create(base::Bind(
1034 &LayerTreeHostContextTestDontUseLostResources::
1035 EmptyReleaseCallback)));
1036 root->AddChild(texture);
1038 scoped_refptr<ContentLayer> mask = ContentLayer::Create(&client_);
1039 mask->SetBounds(gfx::Size(10, 10));
1040 mask->SetAnchorPoint(gfx::PointF());
1042 scoped_refptr<ContentLayer> content_with_mask =
1043 ContentLayer::Create(&client_);
1044 content_with_mask->SetBounds(gfx::Size(10, 10));
1045 content_with_mask->SetAnchorPoint(gfx::PointF());
1046 content_with_mask->SetIsDrawable(true);
1047 content_with_mask->SetMaskLayer(mask.get());
1048 root->AddChild(content_with_mask);
1050 scoped_refptr<VideoLayer> video_color =
1051 VideoLayer::Create(&color_frame_provider_);
1052 video_color->SetBounds(gfx::Size(10, 10));
1053 video_color->SetAnchorPoint(gfx::PointF());
1054 video_color->SetIsDrawable(true);
1055 root->AddChild(video_color);
1057 scoped_refptr<VideoLayer> video_hw =
1058 VideoLayer::Create(&hw_frame_provider_);
1059 video_hw->SetBounds(gfx::Size(10, 10));
1060 video_hw->SetAnchorPoint(gfx::PointF());
1061 video_hw->SetIsDrawable(true);
1062 root->AddChild(video_hw);
1064 scoped_refptr<VideoLayer> video_scaled_hw =
1065 VideoLayer::Create(&scaled_hw_frame_provider_);
1066 video_scaled_hw->SetBounds(gfx::Size(10, 10));
1067 video_scaled_hw->SetAnchorPoint(gfx::PointF());
1068 video_scaled_hw->SetIsDrawable(true);
1069 root->AddChild(video_scaled_hw);
1071 color_video_frame_ = VideoFrame::CreateColorFrame(
1072 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
1073 hw_video_frame_ = VideoFrame::WrapNativeTexture(
1074 make_scoped_ptr(new VideoFrame::MailboxHolder(
1075 mailbox,
1076 sync_point,
1077 VideoFrame::MailboxHolder::TextureNoLongerNeededCallback())),
1078 GL_TEXTURE_2D,
1079 gfx::Size(4, 4),
1080 gfx::Rect(0, 0, 4, 4),
1081 gfx::Size(4, 4),
1082 base::TimeDelta(),
1083 VideoFrame::ReadPixelsCB(),
1084 base::Closure());
1085 scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
1086 make_scoped_ptr(new VideoFrame::MailboxHolder(
1087 mailbox,
1088 sync_point,
1089 VideoFrame::MailboxHolder::TextureNoLongerNeededCallback())),
1090 GL_TEXTURE_2D,
1091 gfx::Size(4, 4),
1092 gfx::Rect(0, 0, 3, 2),
1093 gfx::Size(4, 4),
1094 base::TimeDelta(),
1095 VideoFrame::ReadPixelsCB(),
1096 base::Closure());
1098 color_frame_provider_.set_frame(color_video_frame_);
1099 hw_frame_provider_.set_frame(hw_video_frame_);
1100 scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
1102 if (!delegating_renderer()) {
1103 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
1104 scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
1105 io_surface->SetBounds(gfx::Size(10, 10));
1106 io_surface->SetAnchorPoint(gfx::PointF());
1107 io_surface->SetIsDrawable(true);
1108 io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10));
1109 root->AddChild(io_surface);
1112 // Enable the hud.
1113 LayerTreeDebugState debug_state;
1114 debug_state.show_property_changed_rects = true;
1115 layer_tree_host()->SetDebugState(debug_state);
1117 scoped_refptr<PaintedScrollbarLayer> scrollbar =
1118 PaintedScrollbarLayer::Create(
1119 scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), content->id());
1120 scrollbar->SetBounds(gfx::Size(10, 10));
1121 scrollbar->SetAnchorPoint(gfx::PointF());
1122 scrollbar->SetIsDrawable(true);
1123 root->AddChild(scrollbar);
1125 layer_tree_host()->SetRootLayer(root);
1126 LayerTreeHostContextTest::SetupTree();
1129 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1131 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1132 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
1134 if (host_impl->active_tree()->source_frame_number() == 3) {
1135 // On the third commit we're recovering from context loss. Hardware
1136 // video frames should not be reused by the VideoFrameProvider, but
1137 // software frames can be.
1138 hw_frame_provider_.set_frame(NULL);
1139 scaled_hw_frame_provider_.set_frame(NULL);
1143 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1144 LayerTreeHostImpl::FrameData* frame,
1145 bool result) OVERRIDE {
1146 if (host_impl->active_tree()->source_frame_number() == 2) {
1147 // Lose the context during draw on the second commit. This will cause
1148 // a third commit to recover.
1149 context3d_->set_times_bind_texture_succeeds(0);
1151 return true;
1154 virtual scoped_ptr<OutputSurface> CreateOutputSurface(
1155 bool fallback) OVERRIDE {
1156 // This will get called twice:
1157 // First when we create the initial output surface...
1158 if (layer_tree_host()->source_frame_number() > 0) {
1159 // ... and then again after we forced the context to be lost on the third
1160 // frame. Verify this assumption here.
1161 lost_context_ = true;
1162 EXPECT_EQ(layer_tree_host()->source_frame_number(), 3);
1164 return LayerTreeHostContextTest::CreateOutputSurface(fallback);
1167 virtual void DidCommitAndDrawFrame() OVERRIDE {
1168 ASSERT_TRUE(layer_tree_host()->hud_layer());
1169 // End the test once we know the 3nd frame drew.
1170 if (layer_tree_host()->source_frame_number() < 4) {
1171 layer_tree_host()->root_layer()->SetNeedsDisplay();
1172 layer_tree_host()->SetNeedsCommit();
1173 } else {
1174 EndTest();
1178 virtual void AfterTest() OVERRIDE {
1179 EXPECT_TRUE(lost_context_);
1182 private:
1183 FakeContentLayerClient client_;
1184 bool lost_context_;
1186 FakeOutputSurfaceClient output_surface_client_;
1187 scoped_ptr<FakeOutputSurface> child_output_surface_;
1188 scoped_ptr<ResourceProvider> child_resource_provider_;
1190 scoped_refptr<DelegatedFrameResourceCollection>
1191 delegated_resource_collection_;
1192 scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
1194 scoped_refptr<VideoFrame> color_video_frame_;
1195 scoped_refptr<VideoFrame> hw_video_frame_;
1196 scoped_refptr<VideoFrame> scaled_hw_video_frame_;
1198 FakeVideoFrameProvider color_frame_provider_;
1199 FakeVideoFrameProvider hw_frame_provider_;
1200 FakeVideoFrameProvider scaled_hw_frame_provider_;
1203 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
1205 class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
1206 : public LayerTreeHostContextTest {
1207 public:
1208 virtual void BeginTest() OVERRIDE {
1209 // This must be called immediately after creating LTH, before the first
1210 // OutputSurface is initialized.
1211 ASSERT_TRUE(layer_tree_host()->output_surface_lost());
1213 times_output_surface_created_ = 0;
1215 // Post the SetNeedsCommit before the readback to make sure it is run
1216 // on the main thread before the readback's replacement commit when
1217 // we have a threaded compositor.
1218 PostSetNeedsCommitToMainThread();
1220 char pixels[4];
1221 bool result = layer_tree_host()->CompositeAndReadback(
1222 &pixels, gfx::Rect(1, 1));
1223 EXPECT_EQ(!delegating_renderer(), result);
1224 EXPECT_EQ(1, times_output_surface_created_);
1227 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
1228 EXPECT_TRUE(succeeded);
1229 ++times_output_surface_created_;
1232 virtual void DidCommitAndDrawFrame() OVERRIDE {
1233 EndTest();
1236 virtual void AfterTest() OVERRIDE {
1237 // Should not try to create output surface again after successfully
1238 // created by CompositeAndReadback.
1239 EXPECT_EQ(1, times_output_surface_created_);
1242 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1243 LayerTreeHostImpl::FrameData* frame_data,
1244 bool result) OVERRIDE {
1245 EXPECT_GE(host_impl->active_tree()->source_frame_number(), 0);
1246 EXPECT_LE(host_impl->active_tree()->source_frame_number(), 1);
1247 return true;
1250 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1251 // We should only draw for the readback and the replacement commit.
1252 // The replacement commit will also be the first commit after output
1253 // surface initialization.
1254 EXPECT_GE(host_impl->active_tree()->source_frame_number(), 0);
1255 EXPECT_LE(host_impl->active_tree()->source_frame_number(), 1);
1258 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1259 bool result) OVERRIDE {
1260 // We should only swap for the replacement commit.
1261 EXPECT_EQ(host_impl->active_tree()->source_frame_number(), 1);
1262 EndTest();
1265 private:
1266 int times_output_surface_created_;
1269 SINGLE_AND_MULTI_THREAD_TEST_F(
1270 LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit);
1272 // This test verifies that losing an output surface during a
1273 // simultaneous readback and forced redraw works and does not deadlock.
1274 class LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw
1275 : public LayerTreeHostContextTest {
1276 protected:
1277 static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
1278 static const int kReadbackSourceFrameNumber = 1;
1279 static const int kReadbackReplacementSourceFrameNumber = 2;
1280 static const int kSecondOutputSurfaceInitSourceFrameNumber = 3;
1282 LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw()
1283 : did_react_to_first_commit_(false) {}
1285 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1286 // This enables forced draws after a single prepare to draw failure.
1287 settings->timeout_and_draw_when_animation_checkerboards = true;
1288 settings->maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
1291 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1293 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1294 LayerTreeHostImpl::FrameData* frame_data,
1295 bool result) OVERRIDE {
1296 int sfn = host_impl->active_tree()->source_frame_number();
1297 EXPECT_TRUE(sfn == kFirstOutputSurfaceInitSourceFrameNumber ||
1298 sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1299 sfn == kReadbackSourceFrameNumber)
1300 << sfn;
1302 // Before we react to the failed draw by initiating the forced draw
1303 // sequence, start a readback on the main thread and then lose the context
1304 // to start output surface initialization all at the same time.
1305 if (sfn == kFirstOutputSurfaceInitSourceFrameNumber &&
1306 !did_react_to_first_commit_) {
1307 did_react_to_first_commit_ = true;
1308 PostReadbackToMainThread();
1309 LoseContext();
1312 return false;
1315 virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
1316 bool success) OVERRIDE {
1317 // -1 is for the first output surface initialization.
1318 int sfn = host_impl->active_tree()->source_frame_number();
1319 EXPECT_TRUE(sfn == -1 || sfn == kReadbackReplacementSourceFrameNumber)
1320 << sfn;
1323 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1324 // We should only draw the first commit after output surface initialization
1325 // and attempt to draw the readback commit (which will fail).
1326 // All others should abort because the output surface is lost.
1327 int sfn = host_impl->active_tree()->source_frame_number();
1328 EXPECT_TRUE(sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1329 sfn == kReadbackSourceFrameNumber)
1330 << sfn;
1333 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1334 bool result) OVERRIDE {
1335 // We should only swap the first commit after the second output surface
1336 // initialization.
1337 int sfn = host_impl->active_tree()->source_frame_number();
1338 EXPECT_TRUE(sfn == kSecondOutputSurfaceInitSourceFrameNumber) << sfn;
1339 EndTest();
1342 virtual void AfterTest() OVERRIDE {}
1344 int did_react_to_first_commit_;
1347 MULTI_THREAD_TEST_F(
1348 LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw);
1350 // This test verifies that losing an output surface right before a
1351 // simultaneous readback and forced redraw works and does not deadlock.
1352 class LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit
1353 : public LayerTreeHostContextTest {
1354 protected:
1355 static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
1356 static const int kReadbackSourceFrameNumber = 1;
1357 static const int kForcedDrawCommitSourceFrameNumber = 2;
1358 static const int kSecondOutputSurfaceInitSourceFrameNumber = 2;
1360 LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit()
1361 : did_lose_context_(false) {}
1363 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1364 // This enables forced draws after a single prepare to draw failure.
1365 settings->timeout_and_draw_when_animation_checkerboards = true;
1366 settings->maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
1369 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1371 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1372 LayerTreeHostImpl::FrameData* frame_data,
1373 bool result) OVERRIDE {
1374 int sfn = host_impl->active_tree()->source_frame_number();
1375 EXPECT_TRUE(sfn == kFirstOutputSurfaceInitSourceFrameNumber ||
1376 sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1377 sfn == kReadbackSourceFrameNumber)
1378 << sfn;
1380 // Before we react to the failed draw by initiating the forced draw
1381 // sequence, start a readback on the main thread and then lose the context
1382 // to start output surface initialization all at the same time.
1383 if (sfn == kFirstOutputSurfaceInitSourceFrameNumber && !did_lose_context_) {
1384 did_lose_context_ = true;
1385 LoseContext();
1388 // Returning false will result in a forced draw.
1389 return false;
1392 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
1393 EXPECT_TRUE(succeeded);
1394 if (layer_tree_host()->source_frame_number() > 0) {
1395 // Perform a readback right after the second output surface
1396 // initialization.
1397 char pixels[4];
1398 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
1402 virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
1403 bool success) OVERRIDE {
1404 // -1 is for the first output surface initialization.
1405 int sfn = host_impl->active_tree()->source_frame_number();
1406 EXPECT_TRUE(sfn == -1 || sfn == kFirstOutputSurfaceInitSourceFrameNumber)
1407 << sfn;
1410 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1411 // We should only draw the first commit after output surface initialization
1412 // and attempt to draw the readback commit (which will fail).
1413 // All others should abort because the output surface is lost.
1414 int sfn = host_impl->active_tree()->source_frame_number();
1415 EXPECT_TRUE(sfn == kForcedDrawCommitSourceFrameNumber ||
1416 sfn == kReadbackSourceFrameNumber)
1417 << sfn;
1420 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1421 bool result) OVERRIDE {
1422 // We should only swap the first commit after the second output surface
1423 // initialization.
1424 int sfn = host_impl->active_tree()->source_frame_number();
1425 EXPECT_TRUE(sfn == kForcedDrawCommitSourceFrameNumber) << sfn;
1426 EndTest();
1429 virtual void AfterTest() OVERRIDE {}
1431 int did_lose_context_;
1434 MULTI_THREAD_TEST_F(
1435 LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit);
1437 class ImplSidePaintingLayerTreeHostContextTest
1438 : public LayerTreeHostContextTest {
1439 public:
1440 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1441 settings->impl_side_painting = true;
1445 class LayerTreeHostContextTestImplSidePainting
1446 : public ImplSidePaintingLayerTreeHostContextTest {
1447 public:
1448 virtual void SetupTree() OVERRIDE {
1449 scoped_refptr<Layer> root = Layer::Create();
1450 root->SetBounds(gfx::Size(10, 10));
1451 root->SetAnchorPoint(gfx::PointF());
1452 root->SetIsDrawable(true);
1454 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
1455 picture->SetBounds(gfx::Size(10, 10));
1456 picture->SetAnchorPoint(gfx::PointF());
1457 picture->SetIsDrawable(true);
1458 root->AddChild(picture);
1460 layer_tree_host()->SetRootLayer(root);
1461 LayerTreeHostContextTest::SetupTree();
1464 virtual void BeginTest() OVERRIDE {
1465 times_to_lose_during_commit_ = 1;
1466 PostSetNeedsCommitToMainThread();
1469 virtual void AfterTest() OVERRIDE {}
1471 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
1472 EXPECT_TRUE(succeeded);
1473 EndTest();
1476 private:
1477 FakeContentLayerClient client_;
1480 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
1482 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1483 public:
1484 ScrollbarLayerLostContext() : commits_(0) {}
1486 virtual void BeginTest() OVERRIDE {
1487 scoped_refptr<Layer> scroll_layer = Layer::Create();
1488 scrollbar_layer_ = FakePaintedScrollbarLayer::Create(
1489 false, true, scroll_layer->id());
1490 scrollbar_layer_->SetBounds(gfx::Size(10, 100));
1491 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
1492 layer_tree_host()->root_layer()->AddChild(scroll_layer);
1493 PostSetNeedsCommitToMainThread();
1496 virtual void AfterTest() OVERRIDE {}
1498 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1499 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1501 ++commits_;
1502 switch (commits_) {
1503 case 1:
1504 // First (regular) update, we should upload 2 resources (thumb, and
1505 // backtrack).
1506 EXPECT_EQ(1, scrollbar_layer_->update_count());
1507 LoseContext();
1508 break;
1509 case 2:
1510 // Second update, after the lost context, we should still upload 2
1511 // resources even if the contents haven't changed.
1512 EXPECT_EQ(2, scrollbar_layer_->update_count());
1513 EndTest();
1514 break;
1515 case 3:
1516 // Single thread proxy issues extra commits after context lost.
1517 // http://crbug.com/287250
1518 if (HasImplThread())
1519 NOTREACHED();
1520 break;
1521 default:
1522 NOTREACHED();
1526 private:
1527 int commits_;
1528 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
1531 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1533 class UIResourceLostTest : public LayerTreeHostContextTest {
1534 public:
1535 UIResourceLostTest() : time_step_(0) {}
1536 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1537 settings->texture_id_allocation_chunk_size = 1;
1539 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1540 virtual void AfterTest() OVERRIDE {}
1542 // This is called on the main thread after each commit and
1543 // DidActivateTreeOnThread, with the value of time_step_ at the time
1544 // of the call to DidActivateTreeOnThread. Similar tests will do
1545 // work on the main thread in DidCommit but that is unsuitable because
1546 // the main thread work for these tests must happen after
1547 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1548 // painting.
1549 virtual void StepCompleteOnMainThread(int time_step) = 0;
1551 // Called after DidActivateTreeOnThread. If this is done during the commit,
1552 // the call to StepCompleteOnMainThread will not occur until after
1553 // the commit completes, because the main thread is blocked.
1554 void PostStepCompleteToMainThread() {
1555 proxy()->MainThreadTaskRunner()->PostTask(
1556 FROM_HERE,
1557 base::Bind(
1558 &UIResourceLostTest::StepCompleteOnMainThreadInternal,
1559 base::Unretained(this),
1560 time_step_));
1563 void PostLoseContextToImplThread() {
1564 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1565 base::SingleThreadTaskRunner* task_runner =
1566 HasImplThread() ? ImplThreadTaskRunner()
1567 : base::MessageLoopProxy::current();
1568 task_runner->PostTask(
1569 FROM_HERE,
1570 base::Bind(
1571 &LayerTreeHostContextTest::LoseContext,
1572 base::Unretained(this)));
1575 protected:
1576 int time_step_;
1577 scoped_ptr<FakeScopedUIResource> ui_resource_;
1579 private:
1580 void StepCompleteOnMainThreadInternal(int step) {
1581 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1582 StepCompleteOnMainThread(step);
1586 class UIResourceLostTestSimple : public UIResourceLostTest {
1587 public:
1588 // This is called when the commit is complete and the new layer tree has been
1589 // activated.
1590 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1592 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1593 if (!layer_tree_host()->settings().impl_side_painting) {
1594 StepCompleteOnImplThread(impl);
1595 PostStepCompleteToMainThread();
1596 ++time_step_;
1600 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1601 if (layer_tree_host()->settings().impl_side_painting) {
1602 StepCompleteOnImplThread(impl);
1603 PostStepCompleteToMainThread();
1604 ++time_step_;
1609 // Losing context after an UI resource has been created.
1610 class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
1611 public:
1612 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1613 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1614 switch (step) {
1615 case 0:
1616 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1617 // Expects a valid UIResourceId.
1618 EXPECT_NE(0, ui_resource_->id());
1619 PostSetNeedsCommitToMainThread();
1620 break;
1621 case 4:
1622 // Release resource before ending the test.
1623 ui_resource_.reset();
1624 EndTest();
1625 break;
1626 case 5:
1627 // Single thread proxy issues extra commits after context lost.
1628 // http://crbug.com/287250
1629 if (HasImplThread())
1630 NOTREACHED();
1631 break;
1632 case 6:
1633 NOTREACHED();
1637 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1638 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1639 switch (time_step_) {
1640 case 1:
1641 // The resource should have been created on LTHI after the commit.
1642 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1643 PostSetNeedsCommitToMainThread();
1644 break;
1645 case 2:
1646 LoseContext();
1647 break;
1648 case 3:
1649 // The resources should have been recreated. The bitmap callback should
1650 // have been called once with the resource_lost flag set to true.
1651 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1652 // Resource Id on the impl-side have been recreated as well. Note
1653 // that the same UIResourceId persists after the context lost.
1654 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1655 PostSetNeedsCommitToMainThread();
1656 break;
1661 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
1663 // Losing context before UI resource requests can be commited. Three sequences
1664 // of creation/deletion are considered:
1665 // 1. Create one resource -> Context Lost => Expect the resource to have been
1666 // created.
1667 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1668 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1669 // test_id1_ to have been created.
1670 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1671 // the resource to not exist in the manager.
1672 class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
1673 public:
1674 UIResourceLostBeforeCommit()
1675 : test_id0_(0),
1676 test_id1_(0) {}
1678 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1679 switch (step) {
1680 case 0:
1681 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1682 // Lose the context on the impl thread before the commit.
1683 PostLoseContextToImplThread();
1684 break;
1685 case 2:
1686 // Sequence 2:
1687 // Currently one resource has been created.
1688 test_id0_ = ui_resource_->id();
1689 // Delete this resource.
1690 ui_resource_.reset();
1691 // Create another resource.
1692 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1693 test_id1_ = ui_resource_->id();
1694 // Sanity check that two resource creations return different ids.
1695 EXPECT_NE(test_id0_, test_id1_);
1696 // Lose the context on the impl thread before the commit.
1697 PostLoseContextToImplThread();
1698 break;
1699 case 3:
1700 // Clear the manager of resources.
1701 ui_resource_.reset();
1702 PostSetNeedsCommitToMainThread();
1703 break;
1704 case 4:
1705 // Sequence 3:
1706 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1707 test_id0_ = ui_resource_->id();
1708 // Sanity check the UIResourceId should not be 0.
1709 EXPECT_NE(0, test_id0_);
1710 // Usually ScopedUIResource are deleted from the manager in their
1711 // destructor (so usually ui_resource_.reset()). But here we need
1712 // ui_resource_ for the next step, so call DeleteUIResource directly.
1713 layer_tree_host()->DeleteUIResource(test_id0_);
1714 // Delete the resouce and then lose the context.
1715 PostLoseContextToImplThread();
1716 break;
1717 case 5:
1718 // Release resource before ending the test.
1719 ui_resource_.reset();
1720 EndTest();
1721 break;
1722 case 6:
1723 // Single thread proxy issues extra commits after context lost.
1724 // http://crbug.com/287250
1725 if (HasImplThread())
1726 NOTREACHED();
1727 break;
1728 case 8:
1729 NOTREACHED();
1733 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1734 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1735 switch (time_step_) {
1736 case 1:
1737 // Sequence 1 (continued):
1738 // The first context lost happens before the resources were created,
1739 // and because it resulted in no resources being destroyed, it does not
1740 // trigger resource re-creation.
1741 EXPECT_EQ(1, ui_resource_->resource_create_count);
1742 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1743 // Resource Id on the impl-side has been created.
1744 PostSetNeedsCommitToMainThread();
1745 break;
1746 case 3:
1747 // Sequence 2 (continued):
1748 // The previous resource should have been deleted.
1749 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1750 if (HasImplThread()) {
1751 // The second resource should have been created.
1752 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
1753 } else {
1754 // The extra commit that happens at context lost in the single thread
1755 // proxy changes the timing so that the resource has been destroyed.
1756 // http://crbug.com/287250
1757 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id1_));
1759 // The second resource called the resource callback once and since the
1760 // context is lost, a "resource lost" callback was also issued.
1761 EXPECT_EQ(2, ui_resource_->resource_create_count);
1762 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1763 break;
1764 case 5:
1765 // Sequence 3 (continued):
1766 // Expect the resource callback to have been called once.
1767 EXPECT_EQ(1, ui_resource_->resource_create_count);
1768 // No "resource lost" callbacks.
1769 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1770 // The UI resource id should not be valid
1771 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1772 break;
1776 private:
1777 UIResourceId test_id0_;
1778 UIResourceId test_id1_;
1781 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
1783 // Losing UI resource before the pending trees is activated but after the
1784 // commit. Impl-side-painting only.
1785 class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
1786 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1787 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1788 switch (step) {
1789 case 0:
1790 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1791 PostSetNeedsCommitToMainThread();
1792 break;
1793 case 3:
1794 test_id_ = ui_resource_->id();
1795 ui_resource_.reset();
1796 PostSetNeedsCommitToMainThread();
1797 break;
1798 case 5:
1799 // Release resource before ending the test.
1800 ui_resource_.reset();
1801 EndTest();
1802 break;
1803 case 6:
1804 // Make sure no extra commits happened.
1805 NOTREACHED();
1809 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1810 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1811 switch (time_step_) {
1812 case 2:
1813 PostSetNeedsCommitToMainThread();
1814 break;
1815 case 4:
1816 PostSetNeedsCommitToMainThread();
1817 break;
1821 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1822 switch (time_step_) {
1823 case 1:
1824 // The resource creation callback has been called.
1825 EXPECT_EQ(1, ui_resource_->resource_create_count);
1826 // The resource is not yet lost (sanity check).
1827 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1828 // The resource should not have been created yet on the impl-side.
1829 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1830 LoseContext();
1831 break;
1832 case 3:
1833 LoseContext();
1834 break;
1838 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1839 LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1840 switch (time_step_) {
1841 case 1:
1842 // The pending requests on the impl-side should have been processed.
1843 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1844 break;
1845 case 2:
1846 // The "lost resource" callback should have been called once.
1847 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1848 break;
1849 case 4:
1850 // The resource is deleted and should not be in the manager. Use
1851 // test_id_ since ui_resource_ has been deleted.
1852 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
1853 break;
1856 PostStepCompleteToMainThread();
1857 ++time_step_;
1860 private:
1861 UIResourceId test_id_;
1864 TEST_F(UIResourceLostBeforeActivateTree,
1865 RunMultiThread_DirectRenderer_ImplSidePaint) {
1866 RunTest(true, false, true);
1869 TEST_F(UIResourceLostBeforeActivateTree,
1870 RunMultiThread_DelegatingRenderer_ImplSidePaint) {
1871 RunTest(true, true, true);
1874 // Resources evicted explicitly and by visibility changes.
1875 class UIResourceLostEviction : public UIResourceLostTestSimple {
1876 public:
1877 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1878 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1879 switch (step) {
1880 case 0:
1881 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1882 EXPECT_NE(0, ui_resource_->id());
1883 PostSetNeedsCommitToMainThread();
1884 break;
1885 case 2:
1886 // Make the tree not visible.
1887 PostSetVisibleToMainThread(false);
1888 break;
1889 case 3:
1890 // Release resource before ending the test.
1891 ui_resource_.reset();
1892 EndTest();
1893 break;
1894 case 4:
1895 NOTREACHED();
1899 virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl,
1900 bool visible) OVERRIDE {
1901 TestWebGraphicsContext3D* context = static_cast<TestContextProvider*>(
1902 impl->output_surface()->context_provider().get())->TestContext3d();
1903 if (!visible) {
1904 // All resources should have been evicted.
1905 ASSERT_EQ(0u, context->NumTextures());
1906 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1907 EXPECT_EQ(2, ui_resource_->resource_create_count);
1908 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1909 // Drawing is disabled both because of the evicted resources and
1910 // because the renderer is not visible.
1911 EXPECT_FALSE(impl->CanDraw());
1912 // Make the renderer visible again.
1913 PostSetVisibleToMainThread(true);
1917 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1918 TestWebGraphicsContext3D* context = static_cast<TestContextProvider*>(
1919 impl->output_surface()->context_provider().get())->TestContext3d();
1920 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1921 switch (time_step_) {
1922 case 1:
1923 // The resource should have been created on LTHI after the commit.
1924 ASSERT_EQ(1u, context->NumTextures());
1925 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1926 EXPECT_EQ(1, ui_resource_->resource_create_count);
1927 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1928 EXPECT_TRUE(impl->CanDraw());
1929 // Evict all UI resources. This will trigger a commit.
1930 impl->EvictAllUIResources();
1931 ASSERT_EQ(0u, context->NumTextures());
1932 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1933 EXPECT_EQ(1, ui_resource_->resource_create_count);
1934 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1935 EXPECT_FALSE(impl->CanDraw());
1936 break;
1937 case 2:
1938 // The resource should have been recreated.
1939 ASSERT_EQ(1u, context->NumTextures());
1940 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1941 EXPECT_EQ(2, ui_resource_->resource_create_count);
1942 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1943 EXPECT_TRUE(impl->CanDraw());
1944 break;
1945 case 3:
1946 // The resource should have been recreated after visibility was
1947 // restored.
1948 ASSERT_EQ(1u, context->NumTextures());
1949 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1950 EXPECT_EQ(3, ui_resource_->resource_create_count);
1951 EXPECT_EQ(2, ui_resource_->lost_resource_count);
1952 EXPECT_TRUE(impl->CanDraw());
1953 break;
1958 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1960 class LayerTreeHostContextTestSurfaceCreateCallback
1961 : public LayerTreeHostContextTest {
1962 public:
1963 LayerTreeHostContextTestSurfaceCreateCallback()
1964 : LayerTreeHostContextTest(),
1965 layer_(FakeContentLayer::Create(&client_)),
1966 num_commits_(0) {}
1968 virtual void SetupTree() OVERRIDE {
1969 layer_->SetBounds(gfx::Size(10, 20));
1970 layer_tree_host()->SetRootLayer(layer_);
1971 LayerTreeHostContextTest::SetupTree();
1974 virtual void BeginTest() OVERRIDE {
1975 PostSetNeedsCommitToMainThread();
1978 virtual void DidCommit() OVERRIDE {
1979 switch (num_commits_) {
1980 case 0:
1981 EXPECT_EQ(1u, layer_->output_surface_created_count());
1982 layer_tree_host()->SetNeedsCommit();
1983 break;
1984 case 1:
1985 EXPECT_EQ(1u, layer_->output_surface_created_count());
1986 layer_tree_host()->SetNeedsCommit();
1987 break;
1988 case 2:
1989 EXPECT_EQ(1u, layer_->output_surface_created_count());
1990 break;
1991 case 3:
1992 EXPECT_EQ(2u, layer_->output_surface_created_count());
1993 layer_tree_host()->SetNeedsCommit();
1994 break;
1996 ++num_commits_;
1999 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
2000 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
2001 switch (num_commits_) {
2002 case 0:
2003 break;
2004 case 1:
2005 break;
2006 case 2:
2007 LoseContext();
2008 break;
2009 case 3:
2010 EndTest();
2011 break;
2015 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
2016 EXPECT_TRUE(succeeded);
2019 virtual void AfterTest() OVERRIDE {}
2021 protected:
2022 FakeContentLayerClient client_;
2023 scoped_refptr<FakeContentLayer> layer_;
2024 int num_commits_;
2027 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
2029 } // namespace
2030 } // namespace cc