Add git cl format presubmit warning for extension and apps.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_context.cc
blobbaf2b2ddbad5f0d43995504ebc24e2a96957b848
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<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
80 OVERRIDE {
81 if (times_to_fail_create_) {
82 --times_to_fail_create_;
83 ExpectCreateToFail();
84 return scoped_ptr<FakeOutputSurface>();
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 else
98 return FakeOutputSurface::Create3d(context3d.Pass());
101 scoped_ptr<TestWebGraphicsContext3D> CreateOffscreenContext3d() {
102 if (!context3d_)
103 return scoped_ptr<TestWebGraphicsContext3D>();
105 ++times_offscreen_created_;
107 if (times_to_fail_create_offscreen_) {
108 --times_to_fail_create_offscreen_;
109 ExpectCreateToFail();
110 return scoped_ptr<TestWebGraphicsContext3D>();
113 scoped_ptr<TestWebGraphicsContext3D> offscreen_context3d =
114 TestWebGraphicsContext3D::Create().Pass();
115 DCHECK(offscreen_context3d);
116 context3d_->add_share_group_context(offscreen_context3d.get());
118 return offscreen_context3d.Pass();
121 virtual scoped_refptr<ContextProvider> OffscreenContextProvider() OVERRIDE {
122 if (!offscreen_contexts_.get() ||
123 offscreen_contexts_->DestroyedOnMainThread()) {
124 offscreen_contexts_ =
125 TestContextProvider::Create(CreateOffscreenContext3d());
127 return offscreen_contexts_;
130 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
131 LayerTreeHostImpl* host_impl,
132 LayerTreeHostImpl::FrameData* frame,
133 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
134 EXPECT_EQ(DrawSwapReadbackResult::DRAW_SUCCESS, draw_result);
135 if (!times_to_lose_during_draw_)
136 return draw_result;
138 --times_to_lose_during_draw_;
139 LoseContext();
141 times_to_fail_create_ = times_to_fail_recreate_;
142 times_to_fail_recreate_ = 0;
143 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
144 times_to_fail_recreate_offscreen_ = 0;
146 return draw_result;
149 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
150 committed_at_least_once_ = true;
152 if (!times_to_lose_during_commit_)
153 return;
154 --times_to_lose_during_commit_;
155 LoseContext();
157 times_to_fail_create_ = times_to_fail_recreate_;
158 times_to_fail_recreate_ = 0;
159 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
160 times_to_fail_recreate_offscreen_ = 0;
163 virtual void DidFailToInitializeOutputSurface() OVERRIDE {
164 ++times_create_failed_;
167 virtual void TearDown() OVERRIDE {
168 LayerTreeTest::TearDown();
169 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
172 void ExpectCreateToFail() { ++times_to_expect_create_failed_; }
174 protected:
175 TestWebGraphicsContext3D* context3d_;
176 int times_to_fail_create_;
177 int times_to_lose_during_commit_;
178 int times_to_lose_during_draw_;
179 int times_to_fail_recreate_;
180 int times_to_fail_create_offscreen_;
181 int times_to_fail_recreate_offscreen_;
182 int times_to_expect_create_failed_;
183 int times_create_failed_;
184 int times_offscreen_created_;
185 bool committed_at_least_once_;
186 bool context_should_support_io_surface_;
187 bool fallback_context_works_;
189 scoped_refptr<TestContextProvider> offscreen_contexts_;
192 class LayerTreeHostContextTestLostContextSucceeds
193 : public LayerTreeHostContextTest {
194 public:
195 LayerTreeHostContextTestLostContextSucceeds()
196 : LayerTreeHostContextTest(),
197 test_case_(0),
198 num_losses_(0),
199 num_losses_last_test_case_(-1),
200 recovered_context_(true),
201 first_initialized_(false) {}
203 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
205 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
206 EXPECT_TRUE(succeeded);
208 if (first_initialized_)
209 ++num_losses_;
210 else
211 first_initialized_ = true;
213 recovered_context_ = true;
216 virtual void AfterTest() OVERRIDE { EXPECT_EQ(9u, test_case_); }
218 virtual void DidCommitAndDrawFrame() OVERRIDE {
219 // If the last frame had a context loss, then we'll commit again to
220 // recover.
221 if (!recovered_context_)
222 return;
223 if (times_to_lose_during_commit_)
224 return;
225 if (times_to_lose_during_draw_)
226 return;
228 recovered_context_ = false;
229 if (NextTestCase())
230 InvalidateAndSetNeedsCommit();
231 else
232 EndTest();
235 virtual void InvalidateAndSetNeedsCommit() {
236 // Cause damage so we try to draw.
237 layer_tree_host()->root_layer()->SetNeedsDisplay();
238 layer_tree_host()->SetNeedsCommit();
241 bool NextTestCase() {
242 static const TestCase kTests[] = {
243 // Losing the context and failing to recreate it (or losing it again
244 // immediately) a small number of times should succeed.
245 {1, // times_to_lose_during_commit
246 0, // times_to_lose_during_draw
247 0, // times_to_fail_recreate
248 0, // times_to_fail_recreate_offscreen
249 false, // fallback_context_works
251 {0, // times_to_lose_during_commit
252 1, // times_to_lose_during_draw
253 0, // times_to_fail_recreate
254 0, // times_to_fail_recreate_offscreen
255 false, // fallback_context_works
257 {1, // times_to_lose_during_commit
258 0, // times_to_lose_during_draw
259 3, // times_to_fail_recreate
260 0, // times_to_fail_recreate_offscreen
261 false, // fallback_context_works
263 {0, // times_to_lose_during_commit
264 1, // times_to_lose_during_draw
265 3, // times_to_fail_recreate
266 0, // times_to_fail_recreate_offscreen
267 false, // fallback_context_works
269 {1, // times_to_lose_during_commit
270 0, // times_to_lose_during_draw
271 0, // times_to_fail_recreate
272 3, // times_to_fail_recreate_offscreen
273 false, // fallback_context_works
275 {0, // times_to_lose_during_commit
276 1, // times_to_lose_during_draw
277 0, // times_to_fail_recreate
278 3, // times_to_fail_recreate_offscreen
279 false, // fallback_context_works
281 // Losing the context and recreating it any number of times should
282 // succeed.
283 {10, // times_to_lose_during_commit
284 0, // times_to_lose_during_draw
285 0, // times_to_fail_recreate
286 0, // times_to_fail_recreate_offscreen
287 false, // fallback_context_works
289 {0, // times_to_lose_during_commit
290 10, // times_to_lose_during_draw
291 0, // times_to_fail_recreate
292 0, // times_to_fail_recreate_offscreen
293 false, // fallback_context_works
295 // Losing the context, failing to reinitialize it, and making a fallback
296 // context should work.
297 {0, // times_to_lose_during_commit
298 1, // times_to_lose_during_draw
299 0, // times_to_fail_recreate
300 0, // times_to_fail_recreate_offscreen
301 true, // fallback_context_works
302 }, };
304 if (test_case_ >= arraysize(kTests))
305 return false;
306 // Make sure that we lost our context at least once in the last test run so
307 // the test did something.
308 EXPECT_GT(num_losses_, num_losses_last_test_case_);
309 num_losses_last_test_case_ = num_losses_;
311 times_to_lose_during_commit_ =
312 kTests[test_case_].times_to_lose_during_commit;
313 times_to_lose_during_draw_ = kTests[test_case_].times_to_lose_during_draw;
314 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
315 times_to_fail_recreate_offscreen_ =
316 kTests[test_case_].times_to_fail_recreate_offscreen;
317 fallback_context_works_ = kTests[test_case_].fallback_context_works;
318 ++test_case_;
319 return true;
322 struct TestCase {
323 int times_to_lose_during_commit;
324 int times_to_lose_during_draw;
325 int times_to_fail_recreate;
326 int times_to_fail_recreate_offscreen;
327 bool fallback_context_works;
330 protected:
331 size_t test_case_;
332 int num_losses_;
333 int num_losses_last_test_case_;
334 bool recovered_context_;
335 bool first_initialized_;
338 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
340 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
341 : public LayerTreeHostContextTest {
342 public:
343 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
344 : LayerTreeHostContextTest() {}
346 virtual void WillBeginTest() OVERRIDE {
347 // Override and do not signal SetLayerTreeHostClientReady.
350 virtual void BeginTest() OVERRIDE {
351 PostSetNeedsCommitToMainThread();
352 EndTest();
355 virtual scoped_ptr<OutputSurface> CreateOutputSurface(bool fallback)
356 OVERRIDE {
357 EXPECT_TRUE(false);
358 return scoped_ptr<OutputSurface>();
361 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
362 EXPECT_TRUE(false);
365 virtual void AfterTest() OVERRIDE {
369 MULTI_THREAD_TEST_F(LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
371 class LayerTreeHostContextTestLostContextSucceedsWithContent
372 : public LayerTreeHostContextTestLostContextSucceeds {
373 public:
374 LayerTreeHostContextTestLostContextSucceedsWithContent()
375 : LayerTreeHostContextTestLostContextSucceeds() {}
377 virtual void SetupTree() OVERRIDE {
378 root_ = Layer::Create();
379 root_->SetBounds(gfx::Size(10, 10));
380 root_->SetAnchorPoint(gfx::PointF());
381 root_->SetIsDrawable(true);
383 content_ = FakeContentLayer::Create(&client_);
384 content_->SetBounds(gfx::Size(10, 10));
385 content_->SetAnchorPoint(gfx::PointF());
386 content_->SetIsDrawable(true);
387 if (use_surface_) {
388 content_->SetForceRenderSurface(true);
389 // Filters require us to create an offscreen context.
390 FilterOperations filters;
391 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
392 content_->SetFilters(filters);
393 content_->SetBackgroundFilters(filters);
396 root_->AddChild(content_);
398 layer_tree_host()->SetRootLayer(root_);
399 LayerTreeHostContextTest::SetupTree();
402 virtual void InvalidateAndSetNeedsCommit() OVERRIDE {
403 // Invalidate the render surface so we don't try to use a cached copy of the
404 // surface. We want to make sure to test the drawing paths for drawing to
405 // a child surface.
406 content_->SetNeedsDisplay();
407 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
410 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
411 FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>(
412 host_impl->active_tree()->root_layer()->children()[0]);
413 // Even though the context was lost, we should have a resource. The
414 // TestWebGraphicsContext3D ensures that this resource is created with
415 // the active context.
416 EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
418 ContextProvider* contexts = host_impl->offscreen_context_provider();
419 if (use_surface_) {
420 ASSERT_TRUE(contexts);
421 EXPECT_TRUE(contexts->ContextGL());
422 // TODO(danakj): Make a fake GrContext.
423 // EXPECT_TRUE(contexts->GrContext());
424 } else {
425 EXPECT_FALSE(contexts);
429 virtual void AfterTest() OVERRIDE {
430 LayerTreeHostContextTestLostContextSucceeds::AfterTest();
431 if (use_surface_) {
432 // 1 create to start with +
433 // 4 from test cases that lose the offscreen context directly +
434 // 2 from test cases that create a fallback +
435 // All the test cases that recreate both contexts only once
436 // per time it is lost.
437 EXPECT_EQ(4 + 1 + 2 + num_losses_, times_offscreen_created_);
438 } else {
439 EXPECT_EQ(0, times_offscreen_created_);
443 protected:
444 bool use_surface_;
445 FakeContentLayerClient client_;
446 scoped_refptr<Layer> root_;
447 scoped_refptr<ContentLayer> content_;
450 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
451 NoSurface_SingleThread_DirectRenderer) {
452 use_surface_ = false;
453 RunTest(false, false, false);
456 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
457 NoSurface_SingleThread_DelegatingRenderer) {
458 use_surface_ = false;
459 RunTest(false, true, false);
462 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
463 NoSurface_MultiThread_DirectRenderer_MainThreadPaint) {
464 use_surface_ = false;
465 RunTest(true, false, false);
468 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
469 NoSurface_MultiThread_DelegatingRenderer_MainThreadPaint) {
470 use_surface_ = false;
471 RunTest(true, true, false);
474 // Surfaces don't exist with a delegating renderer.
475 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
476 WithSurface_SingleThread_DirectRenderer) {
477 use_surface_ = true;
478 RunTest(false, false, false);
481 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
482 WithSurface_MultiThread_DirectRenderer_MainThreadPaint) {
483 use_surface_ = true;
484 RunTest(true, false, false);
487 class LayerTreeHostContextTestCreateOutputSurfaceFails
488 : public LayerTreeHostContextTest {
489 public:
490 // Run a test that initially fails OutputSurface creation |times_to_fail|
491 // times. If |expect_fallback_attempt| is |true|, an attempt to create a
492 // fallback/software OutputSurface is expected to occur.
493 LayerTreeHostContextTestCreateOutputSurfaceFails(int times_to_fail,
494 bool expect_fallback_attempt,
495 bool expect_to_give_up)
496 : times_to_fail_(times_to_fail),
497 expect_fallback_attempt_(expect_fallback_attempt),
498 expect_to_give_up_(expect_to_give_up),
499 did_attempt_fallback_(false),
500 times_initialized_(0) {}
502 virtual void BeginTest() OVERRIDE {
503 times_to_fail_create_ = times_to_fail_;
504 PostSetNeedsCommitToMainThread();
507 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
508 OVERRIDE {
509 scoped_ptr<FakeOutputSurface> surface =
510 LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
512 if (surface)
513 EXPECT_EQ(times_to_fail_, times_create_failed_);
515 did_attempt_fallback_ = fallback;
516 return surface.Pass();
519 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
520 if (succeeded)
521 times_initialized_++;
522 else
523 EndTest();
526 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
527 EndTest();
530 virtual void AfterTest() OVERRIDE {
531 EXPECT_EQ(times_to_fail_, times_create_failed_);
532 EXPECT_EQ(expect_to_give_up_, times_initialized_ == 0);
533 EXPECT_EQ(expect_fallback_attempt_, did_attempt_fallback_);
536 private:
537 int times_to_fail_;
538 bool expect_fallback_attempt_;
539 bool expect_to_give_up_;
540 bool did_attempt_fallback_;
541 int times_initialized_;
544 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
545 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
546 public:
547 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
548 : LayerTreeHostContextTestCreateOutputSurfaceFails(1, false, false) {}
551 SINGLE_AND_MULTI_THREAD_TEST_F(
552 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce);
554 // After 4 failures we expect an attempt to create a fallback/software
555 // OutputSurface.
556 class LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback
557 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
558 public:
559 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback()
560 : LayerTreeHostContextTestCreateOutputSurfaceFails(4, true, false) {}
563 SINGLE_AND_MULTI_THREAD_TEST_F(
564 LayerTreeHostContextTestCreateOutputSurfaceFailsWithFallback);
566 // If we fail that often, we should be giving up cleanly.
567 class LayerTreeHostContextTestCreateOutputSurfaceIsHopeless
568 : public LayerTreeHostContextTestCreateOutputSurfaceFails {
569 public:
570 LayerTreeHostContextTestCreateOutputSurfaceIsHopeless()
571 : LayerTreeHostContextTestCreateOutputSurfaceFails(5, true, true) {}
574 SINGLE_AND_MULTI_THREAD_TEST_F(
575 LayerTreeHostContextTestCreateOutputSurfaceIsHopeless);
578 class LayerTreeHostContextTestOffscreenContextFails
579 : public LayerTreeHostContextTest {
580 public:
581 virtual void SetupTree() OVERRIDE {
582 root_ = Layer::Create();
583 root_->SetBounds(gfx::Size(10, 10));
584 root_->SetAnchorPoint(gfx::PointF());
585 root_->SetIsDrawable(true);
587 content_ = FakeContentLayer::Create(&client_);
588 content_->SetBounds(gfx::Size(10, 10));
589 content_->SetAnchorPoint(gfx::PointF());
590 content_->SetIsDrawable(true);
591 content_->SetForceRenderSurface(true);
592 // Filters require us to create an offscreen context.
593 FilterOperations filters;
594 filters.Append(FilterOperation::CreateGrayscaleFilter(0.5f));
595 content_->SetFilters(filters);
596 content_->SetBackgroundFilters(filters);
598 root_->AddChild(content_);
600 layer_tree_host()->SetRootLayer(root_);
601 LayerTreeHostContextTest::SetupTree();
604 virtual void BeginTest() OVERRIDE {
605 times_to_fail_create_offscreen_ = 1;
606 PostSetNeedsCommitToMainThread();
609 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
610 ContextProvider* contexts = host_impl->offscreen_context_provider();
611 EXPECT_FALSE(contexts);
613 // This did not lead to create failure.
614 times_to_expect_create_failed_ = 0;
615 EndTest();
618 virtual void AfterTest() OVERRIDE {}
620 protected:
621 FakeContentLayerClient client_;
622 scoped_refptr<Layer> root_;
623 scoped_refptr<ContentLayer> content_;
626 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestOffscreenContextFails);
628 class LayerTreeHostContextTestLostContextFails
629 : public LayerTreeHostContextTest {
630 public:
631 LayerTreeHostContextTestLostContextFails()
632 : LayerTreeHostContextTest(), num_commits_(0), first_initialized_(false) {
633 times_to_lose_during_commit_ = 1;
636 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
638 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
639 if (first_initialized_) {
640 EXPECT_FALSE(succeeded);
641 EndTest();
642 } else {
643 first_initialized_ = true;
647 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
648 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
650 ++num_commits_;
651 if (num_commits_ == 1) {
652 // When the context is ok, we should have these things.
653 EXPECT_TRUE(host_impl->output_surface());
654 EXPECT_TRUE(host_impl->renderer());
655 EXPECT_TRUE(host_impl->resource_provider());
656 return;
659 // When context recreation fails we shouldn't be left with any of them.
660 EXPECT_FALSE(host_impl->output_surface());
661 EXPECT_FALSE(host_impl->renderer());
662 EXPECT_FALSE(host_impl->resource_provider());
665 virtual void AfterTest() OVERRIDE {}
667 private:
668 int num_commits_;
669 bool first_initialized_;
672 class LayerTreeHostContextTestLostContextAndEvictTextures
673 : public LayerTreeHostContextTest {
674 public:
675 LayerTreeHostContextTestLostContextAndEvictTextures()
676 : LayerTreeHostContextTest(),
677 layer_(FakeContentLayer::Create(&client_)),
678 impl_host_(0),
679 num_commits_(0) {}
681 virtual void SetupTree() OVERRIDE {
682 layer_->SetBounds(gfx::Size(10, 20));
683 layer_tree_host()->SetRootLayer(layer_);
684 LayerTreeHostContextTest::SetupTree();
687 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
689 void PostEvictTextures() {
690 if (HasImplThread()) {
691 ImplThreadTaskRunner()->PostTask(
692 FROM_HERE,
693 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
694 EvictTexturesOnImplThread,
695 base::Unretained(this)));
696 } else {
697 DebugScopedSetImplThread impl(proxy());
698 EvictTexturesOnImplThread();
702 void EvictTexturesOnImplThread() {
703 impl_host_->EvictTexturesForTesting();
704 if (lose_after_evict_)
705 LoseContext();
708 virtual void DidCommitAndDrawFrame() OVERRIDE {
709 if (num_commits_ > 1)
710 return;
711 EXPECT_TRUE(layer_->HaveBackingAt(0, 0));
712 PostEvictTextures();
715 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
716 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
717 if (num_commits_ > 1)
718 return;
719 ++num_commits_;
720 if (!lose_after_evict_)
721 LoseContext();
722 impl_host_ = impl;
725 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
726 EXPECT_TRUE(succeeded);
727 EndTest();
730 virtual void AfterTest() OVERRIDE {}
732 protected:
733 bool lose_after_evict_;
734 FakeContentLayerClient client_;
735 scoped_refptr<FakeContentLayer> layer_;
736 LayerTreeHostImpl* impl_host_;
737 int num_commits_;
740 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
741 LoseAfterEvict_SingleThread_DirectRenderer) {
742 lose_after_evict_ = true;
743 RunTest(false, false, false);
746 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
747 LoseAfterEvict_SingleThread_DelegatingRenderer) {
748 lose_after_evict_ = true;
749 RunTest(false, true, false);
752 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
753 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) {
754 lose_after_evict_ = true;
755 RunTest(true, false, false);
758 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
759 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
760 lose_after_evict_ = true;
761 RunTest(true, true, false);
764 // Flaky on all platforms, http://crbug.com/310979
765 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
766 DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
767 lose_after_evict_ = true;
768 RunTest(true, true, true);
771 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
772 LoseBeforeEvict_SingleThread_DirectRenderer) {
773 lose_after_evict_ = false;
774 RunTest(false, false, false);
777 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
778 LoseBeforeEvict_SingleThread_DelegatingRenderer) {
779 lose_after_evict_ = false;
780 RunTest(false, true, false);
783 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
784 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) {
785 lose_after_evict_ = false;
786 RunTest(true, false, false);
789 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
790 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) {
791 lose_after_evict_ = false;
792 RunTest(true, false, true);
795 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
796 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
797 lose_after_evict_ = false;
798 RunTest(true, true, false);
801 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
802 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
803 lose_after_evict_ = false;
804 RunTest(true, true, true);
807 class LayerTreeHostContextTestLostContextWhileUpdatingResources
808 : public LayerTreeHostContextTest {
809 public:
810 LayerTreeHostContextTestLostContextWhileUpdatingResources()
811 : parent_(FakeContentLayer::Create(&client_)),
812 num_children_(50),
813 times_to_lose_on_end_query_(3) {}
815 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() OVERRIDE {
816 scoped_ptr<TestWebGraphicsContext3D> context =
817 LayerTreeHostContextTest::CreateContext3d();
818 if (times_to_lose_on_end_query_) {
819 --times_to_lose_on_end_query_;
820 context->set_times_end_query_succeeds(5);
822 return context.Pass();
825 virtual void SetupTree() OVERRIDE {
826 parent_->SetBounds(gfx::Size(num_children_, 1));
828 for (int i = 0; i < num_children_; i++) {
829 scoped_refptr<FakeContentLayer> child =
830 FakeContentLayer::Create(&client_);
831 child->SetPosition(gfx::PointF(i, 0.f));
832 child->SetBounds(gfx::Size(1, 1));
833 parent_->AddChild(child);
836 layer_tree_host()->SetRootLayer(parent_);
837 LayerTreeHostContextTest::SetupTree();
840 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
842 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
843 EXPECT_EQ(0, times_to_lose_on_end_query_);
844 EndTest();
847 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
848 EXPECT_TRUE(succeeded);
851 virtual void AfterTest() OVERRIDE {
852 EXPECT_EQ(0, times_to_lose_on_end_query_);
855 private:
856 FakeContentLayerClient client_;
857 scoped_refptr<FakeContentLayer> parent_;
858 int num_children_;
859 int times_to_lose_on_end_query_;
862 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
863 LayerTreeHostContextTestLostContextWhileUpdatingResources);
865 class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest {
866 public:
867 LayerTreeHostContextTestLayersNotified()
868 : LayerTreeHostContextTest(), num_commits_(0) {}
870 virtual void SetupTree() OVERRIDE {
871 root_ = FakeContentLayer::Create(&client_);
872 child_ = FakeContentLayer::Create(&client_);
873 grandchild_ = FakeContentLayer::Create(&client_);
875 root_->AddChild(child_);
876 child_->AddChild(grandchild_);
878 layer_tree_host()->SetRootLayer(root_);
879 LayerTreeHostContextTest::SetupTree();
882 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
884 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
885 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
887 FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>(
888 host_impl->active_tree()->root_layer());
889 FakeContentLayerImpl* child =
890 static_cast<FakeContentLayerImpl*>(root->children()[0]);
891 FakeContentLayerImpl* grandchild =
892 static_cast<FakeContentLayerImpl*>(child->children()[0]);
894 ++num_commits_;
895 switch (num_commits_) {
896 case 1:
897 EXPECT_EQ(0u, root->lost_output_surface_count());
898 EXPECT_EQ(0u, child->lost_output_surface_count());
899 EXPECT_EQ(0u, grandchild->lost_output_surface_count());
900 // Lose the context and struggle to recreate it.
901 LoseContext();
902 times_to_fail_create_ = 1;
903 break;
904 case 2:
905 EXPECT_GE(1u, root->lost_output_surface_count());
906 EXPECT_GE(1u, child->lost_output_surface_count());
907 EXPECT_GE(1u, grandchild->lost_output_surface_count());
908 EndTest();
909 break;
910 default:
911 NOTREACHED();
915 virtual void AfterTest() OVERRIDE {}
917 private:
918 int num_commits_;
920 FakeContentLayerClient client_;
921 scoped_refptr<FakeContentLayer> root_;
922 scoped_refptr<FakeContentLayer> child_;
923 scoped_refptr<FakeContentLayer> grandchild_;
926 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
928 class LayerTreeHostContextTestDontUseLostResources
929 : public LayerTreeHostContextTest {
930 public:
931 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
932 context_should_support_io_surface_ = true;
934 child_output_surface_ = FakeOutputSurface::Create3d();
935 child_output_surface_->BindToClient(&output_surface_client_);
936 child_resource_provider_ = ResourceProvider::Create(
937 child_output_surface_.get(), NULL, 0, false, 1);
940 static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
942 virtual void SetupTree() OVERRIDE {
943 gpu::gles2::GLES2Interface* gl =
944 child_output_surface_->context_provider()->ContextGL();
946 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
948 scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
949 pass_for_quad->SetNew(
950 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
951 RenderPass::Id(2, 1),
952 gfx::Rect(0, 0, 10, 10),
953 gfx::Rect(0, 0, 10, 10),
954 gfx::Transform());
956 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
957 pass->SetNew(RenderPass::Id(1, 1),
958 gfx::Rect(0, 0, 10, 10),
959 gfx::Rect(0, 0, 10, 10),
960 gfx::Transform());
961 pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
962 RenderPass::Id(2, 1));
964 frame_data->render_pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
965 frame_data->render_pass_list.push_back(pass.PassAs<RenderPass>());
967 delegated_resource_collection_ = new DelegatedFrameResourceCollection;
968 delegated_frame_provider_ = new DelegatedFrameProvider(
969 delegated_resource_collection_.get(), frame_data.Pass());
971 ResourceProvider::ResourceId resource =
972 child_resource_provider_->CreateResource(
973 gfx::Size(4, 4),
974 GL_CLAMP_TO_EDGE,
975 ResourceProvider::TextureUsageAny,
976 RGBA_8888);
977 ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
978 resource);
980 gpu::Mailbox mailbox;
981 gl->GenMailboxCHROMIUM(mailbox.name);
982 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
984 scoped_refptr<Layer> root = Layer::Create();
985 root->SetBounds(gfx::Size(10, 10));
986 root->SetAnchorPoint(gfx::PointF());
987 root->SetIsDrawable(true);
989 scoped_refptr<FakeDelegatedRendererLayer> delegated =
990 FakeDelegatedRendererLayer::Create(delegated_frame_provider_.get());
991 delegated->SetBounds(gfx::Size(10, 10));
992 delegated->SetAnchorPoint(gfx::PointF());
993 delegated->SetIsDrawable(true);
994 root->AddChild(delegated);
996 scoped_refptr<ContentLayer> content = ContentLayer::Create(&client_);
997 content->SetBounds(gfx::Size(10, 10));
998 content->SetAnchorPoint(gfx::PointF());
999 content->SetIsDrawable(true);
1000 root->AddChild(content);
1002 scoped_refptr<TextureLayer> texture = TextureLayer::CreateForMailbox(NULL);
1003 texture->SetBounds(gfx::Size(10, 10));
1004 texture->SetAnchorPoint(gfx::PointF());
1005 texture->SetIsDrawable(true);
1006 texture->SetTextureMailbox(
1007 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1008 SingleReleaseCallback::Create(
1009 base::Bind(&LayerTreeHostContextTestDontUseLostResources::
1010 EmptyReleaseCallback)));
1011 root->AddChild(texture);
1013 scoped_refptr<ContentLayer> mask = ContentLayer::Create(&client_);
1014 mask->SetBounds(gfx::Size(10, 10));
1015 mask->SetAnchorPoint(gfx::PointF());
1017 scoped_refptr<ContentLayer> content_with_mask =
1018 ContentLayer::Create(&client_);
1019 content_with_mask->SetBounds(gfx::Size(10, 10));
1020 content_with_mask->SetAnchorPoint(gfx::PointF());
1021 content_with_mask->SetIsDrawable(true);
1022 content_with_mask->SetMaskLayer(mask.get());
1023 root->AddChild(content_with_mask);
1025 scoped_refptr<VideoLayer> video_color =
1026 VideoLayer::Create(&color_frame_provider_);
1027 video_color->SetBounds(gfx::Size(10, 10));
1028 video_color->SetAnchorPoint(gfx::PointF());
1029 video_color->SetIsDrawable(true);
1030 root->AddChild(video_color);
1032 scoped_refptr<VideoLayer> video_hw =
1033 VideoLayer::Create(&hw_frame_provider_);
1034 video_hw->SetBounds(gfx::Size(10, 10));
1035 video_hw->SetAnchorPoint(gfx::PointF());
1036 video_hw->SetIsDrawable(true);
1037 root->AddChild(video_hw);
1039 scoped_refptr<VideoLayer> video_scaled_hw =
1040 VideoLayer::Create(&scaled_hw_frame_provider_);
1041 video_scaled_hw->SetBounds(gfx::Size(10, 10));
1042 video_scaled_hw->SetAnchorPoint(gfx::PointF());
1043 video_scaled_hw->SetIsDrawable(true);
1044 root->AddChild(video_scaled_hw);
1046 color_video_frame_ = VideoFrame::CreateColorFrame(
1047 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
1048 hw_video_frame_ =
1049 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
1050 mailbox, GL_TEXTURE_2D, sync_point)),
1051 media::VideoFrame::ReleaseMailboxCB(),
1052 gfx::Size(4, 4),
1053 gfx::Rect(0, 0, 4, 4),
1054 gfx::Size(4, 4),
1055 base::TimeDelta(),
1056 VideoFrame::ReadPixelsCB());
1057 scaled_hw_video_frame_ =
1058 VideoFrame::WrapNativeTexture(make_scoped_ptr(new gpu::MailboxHolder(
1059 mailbox, GL_TEXTURE_2D, sync_point)),
1060 media::VideoFrame::ReleaseMailboxCB(),
1061 gfx::Size(4, 4),
1062 gfx::Rect(0, 0, 3, 2),
1063 gfx::Size(4, 4),
1064 base::TimeDelta(),
1065 VideoFrame::ReadPixelsCB());
1067 color_frame_provider_.set_frame(color_video_frame_);
1068 hw_frame_provider_.set_frame(hw_video_frame_);
1069 scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
1071 if (!delegating_renderer()) {
1072 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
1073 scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
1074 io_surface->SetBounds(gfx::Size(10, 10));
1075 io_surface->SetAnchorPoint(gfx::PointF());
1076 io_surface->SetIsDrawable(true);
1077 io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10));
1078 root->AddChild(io_surface);
1081 // Enable the hud.
1082 LayerTreeDebugState debug_state;
1083 debug_state.show_property_changed_rects = true;
1084 layer_tree_host()->SetDebugState(debug_state);
1086 scoped_refptr<PaintedScrollbarLayer> scrollbar =
1087 PaintedScrollbarLayer::Create(
1088 scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), content->id());
1089 scrollbar->SetBounds(gfx::Size(10, 10));
1090 scrollbar->SetAnchorPoint(gfx::PointF());
1091 scrollbar->SetIsDrawable(true);
1092 root->AddChild(scrollbar);
1094 layer_tree_host()->SetRootLayer(root);
1095 LayerTreeHostContextTest::SetupTree();
1098 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1100 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1101 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
1103 if (host_impl->active_tree()->source_frame_number() == 3) {
1104 // On the third commit we're recovering from context loss. Hardware
1105 // video frames should not be reused by the VideoFrameProvider, but
1106 // software frames can be.
1107 hw_frame_provider_.set_frame(NULL);
1108 scaled_hw_frame_provider_.set_frame(NULL);
1112 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1113 LayerTreeHostImpl* host_impl,
1114 LayerTreeHostImpl::FrameData* frame,
1115 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1116 if (host_impl->active_tree()->source_frame_number() == 2) {
1117 // Lose the context during draw on the second commit. This will cause
1118 // a third commit to recover.
1119 context3d_->set_times_bind_texture_succeeds(0);
1121 return draw_result;
1124 virtual scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface(bool fallback)
1125 OVERRIDE {
1126 // This will get called twice:
1127 // First when we create the initial output surface...
1128 if (layer_tree_host()->source_frame_number() > 0) {
1129 // ... and then again after we forced the context to be lost on the third
1130 // frame. Verify this assumption here.
1131 lost_context_ = true;
1132 EXPECT_EQ(layer_tree_host()->source_frame_number(), 3);
1134 return LayerTreeHostContextTest::CreateFakeOutputSurface(fallback);
1137 virtual void DidCommitAndDrawFrame() OVERRIDE {
1138 ASSERT_TRUE(layer_tree_host()->hud_layer());
1139 // End the test once we know the 3nd frame drew.
1140 if (layer_tree_host()->source_frame_number() < 4) {
1141 layer_tree_host()->root_layer()->SetNeedsDisplay();
1142 layer_tree_host()->SetNeedsCommit();
1143 } else {
1144 EndTest();
1148 virtual void AfterTest() OVERRIDE { EXPECT_TRUE(lost_context_); }
1150 private:
1151 FakeContentLayerClient client_;
1152 bool lost_context_;
1154 FakeOutputSurfaceClient output_surface_client_;
1155 scoped_ptr<FakeOutputSurface> child_output_surface_;
1156 scoped_ptr<ResourceProvider> child_resource_provider_;
1158 scoped_refptr<DelegatedFrameResourceCollection>
1159 delegated_resource_collection_;
1160 scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
1162 scoped_refptr<VideoFrame> color_video_frame_;
1163 scoped_refptr<VideoFrame> hw_video_frame_;
1164 scoped_refptr<VideoFrame> scaled_hw_video_frame_;
1166 FakeVideoFrameProvider color_frame_provider_;
1167 FakeVideoFrameProvider hw_frame_provider_;
1168 FakeVideoFrameProvider scaled_hw_frame_provider_;
1171 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
1173 class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
1174 : public LayerTreeHostContextTest {
1175 public:
1176 virtual void BeginTest() OVERRIDE {
1177 // This must be called immediately after creating LTH, before the first
1178 // OutputSurface is initialized.
1179 ASSERT_TRUE(layer_tree_host()->output_surface_lost());
1181 times_output_surface_created_ = 0;
1183 // Post the SetNeedsCommit before the readback to make sure it is run
1184 // on the main thread before the readback's replacement commit when
1185 // we have a threaded compositor.
1186 PostSetNeedsCommitToMainThread();
1188 char pixels[4];
1189 bool result =
1190 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(1, 1));
1191 EXPECT_EQ(!delegating_renderer(), result);
1192 EXPECT_EQ(1, times_output_surface_created_);
1195 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
1196 EXPECT_TRUE(succeeded);
1197 ++times_output_surface_created_;
1200 virtual void DidCommitAndDrawFrame() OVERRIDE { EndTest(); }
1202 virtual void AfterTest() OVERRIDE {
1203 // Should not try to create output surface again after successfully
1204 // created by CompositeAndReadback.
1205 EXPECT_EQ(1, times_output_surface_created_);
1208 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1209 LayerTreeHostImpl* host_impl,
1210 LayerTreeHostImpl::FrameData* frame_data,
1211 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1212 EXPECT_GE(host_impl->active_tree()->source_frame_number(), 0);
1213 EXPECT_LE(host_impl->active_tree()->source_frame_number(), 1);
1214 return draw_result;
1217 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1218 // We should only draw for the readback and the replacement commit.
1219 // The replacement commit will also be the first commit after output
1220 // surface initialization.
1221 EXPECT_GE(host_impl->active_tree()->source_frame_number(), 0);
1222 EXPECT_LE(host_impl->active_tree()->source_frame_number(), 1);
1225 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1226 bool result) OVERRIDE {
1227 // We should only swap for the replacement commit.
1228 EXPECT_EQ(host_impl->active_tree()->source_frame_number(), 1);
1229 EndTest();
1232 private:
1233 int times_output_surface_created_;
1236 SINGLE_AND_MULTI_THREAD_TEST_F(
1237 LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit);
1239 // This test verifies that losing an output surface during a
1240 // simultaneous readback and forced redraw works and does not deadlock.
1241 class LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw
1242 : public LayerTreeHostContextTest {
1243 protected:
1244 static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
1245 static const int kReadbackSourceFrameNumber = 1;
1246 static const int kReadbackReplacementSourceFrameNumber = 2;
1247 static const int kSecondOutputSurfaceInitSourceFrameNumber = 3;
1249 LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw()
1250 : did_react_to_first_commit_(false) {}
1252 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1253 // This enables forced draws after a single prepare to draw failure.
1254 settings->timeout_and_draw_when_animation_checkerboards = true;
1255 settings->maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
1258 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1260 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1261 LayerTreeHostImpl* host_impl,
1262 LayerTreeHostImpl::FrameData* frame_data,
1263 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1264 int sfn = host_impl->active_tree()->source_frame_number();
1265 EXPECT_TRUE(sfn == kFirstOutputSurfaceInitSourceFrameNumber ||
1266 sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1267 sfn == kReadbackSourceFrameNumber)
1268 << sfn;
1270 // Before we react to the failed draw by initiating the forced draw
1271 // sequence, start a readback on the main thread and then lose the context
1272 // to start output surface initialization all at the same time.
1273 if (sfn == kFirstOutputSurfaceInitSourceFrameNumber &&
1274 !did_react_to_first_commit_) {
1275 did_react_to_first_commit_ = true;
1276 PostReadbackToMainThread();
1277 LoseContext();
1280 return DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
1283 virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
1284 bool success) OVERRIDE {
1285 // -1 is for the first output surface initialization.
1286 int sfn = host_impl->active_tree()->source_frame_number();
1287 EXPECT_TRUE(sfn == -1 || sfn == kReadbackReplacementSourceFrameNumber)
1288 << sfn;
1291 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1292 // We should only draw the first commit after output surface initialization
1293 // and attempt to draw the readback commit (which will fail).
1294 // All others should abort because the output surface is lost.
1295 int sfn = host_impl->active_tree()->source_frame_number();
1296 EXPECT_TRUE(sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1297 sfn == kReadbackSourceFrameNumber)
1298 << sfn;
1301 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1302 bool result) OVERRIDE {
1303 // We should only swap the first commit after the second output surface
1304 // initialization.
1305 int sfn = host_impl->active_tree()->source_frame_number();
1306 EXPECT_TRUE(sfn == kSecondOutputSurfaceInitSourceFrameNumber) << sfn;
1307 EndTest();
1310 virtual void AfterTest() OVERRIDE {}
1312 int did_react_to_first_commit_;
1315 MULTI_THREAD_TEST_F(
1316 LayerTreeHostContextTestLoseOutputSurfaceDuringReadbackAndForcedDraw);
1318 // This test verifies that losing an output surface right before a
1319 // simultaneous readback and forced redraw works and does not deadlock.
1320 class LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit
1321 : public LayerTreeHostContextTest {
1322 protected:
1323 static const int kFirstOutputSurfaceInitSourceFrameNumber = 0;
1324 static const int kReadbackSourceFrameNumber = 1;
1325 static const int kForcedDrawCommitSourceFrameNumber = 2;
1326 static const int kSecondOutputSurfaceInitSourceFrameNumber = 2;
1328 LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit()
1329 : did_lose_context_(false) {}
1331 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1332 // This enables forced draws after a single prepare to draw failure.
1333 settings->timeout_and_draw_when_animation_checkerboards = true;
1334 settings->maximum_number_of_failed_draws_before_draw_is_forced_ = 1;
1337 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1339 virtual DrawSwapReadbackResult::DrawResult PrepareToDrawOnThread(
1340 LayerTreeHostImpl* host_impl,
1341 LayerTreeHostImpl::FrameData* frame_data,
1342 DrawSwapReadbackResult::DrawResult draw_result) OVERRIDE {
1343 int sfn = host_impl->active_tree()->source_frame_number();
1344 EXPECT_TRUE(sfn == kFirstOutputSurfaceInitSourceFrameNumber ||
1345 sfn == kSecondOutputSurfaceInitSourceFrameNumber ||
1346 sfn == kReadbackSourceFrameNumber)
1347 << sfn;
1349 // Before we react to the failed draw by initiating the forced draw
1350 // sequence, start a readback on the main thread and then lose the context
1351 // to start output surface initialization all at the same time.
1352 if (sfn == kFirstOutputSurfaceInitSourceFrameNumber && !did_lose_context_) {
1353 did_lose_context_ = true;
1354 LoseContext();
1357 // Returning false will result in a forced draw.
1358 return DrawSwapReadbackResult::DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
1361 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
1362 EXPECT_TRUE(succeeded);
1363 if (layer_tree_host()->source_frame_number() > 0) {
1364 // Perform a readback right after the second output surface
1365 // initialization.
1366 char pixels[4];
1367 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
1371 virtual void InitializedRendererOnThread(LayerTreeHostImpl* host_impl,
1372 bool success) OVERRIDE {
1373 // -1 is for the first output surface initialization.
1374 int sfn = host_impl->active_tree()->source_frame_number();
1375 EXPECT_TRUE(sfn == -1 || sfn == kFirstOutputSurfaceInitSourceFrameNumber)
1376 << sfn;
1379 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1380 // We should only draw the first commit after output surface initialization
1381 // and attempt to draw the readback commit (which will fail).
1382 // All others should abort because the output surface is lost.
1383 int sfn = host_impl->active_tree()->source_frame_number();
1384 EXPECT_TRUE(sfn == kForcedDrawCommitSourceFrameNumber ||
1385 sfn == kReadbackSourceFrameNumber)
1386 << sfn;
1389 virtual void SwapBuffersOnThread(LayerTreeHostImpl* host_impl,
1390 bool result) OVERRIDE {
1391 // We should only swap the first commit after the second output surface
1392 // initialization.
1393 int sfn = host_impl->active_tree()->source_frame_number();
1394 EXPECT_TRUE(sfn == kForcedDrawCommitSourceFrameNumber) << sfn;
1395 EndTest();
1398 virtual void AfterTest() OVERRIDE {}
1400 int did_lose_context_;
1403 MULTI_THREAD_TEST_F(
1404 LayerTreeHostContextTestReadbackWithForcedDrawAndOutputSurfaceInit);
1406 class ImplSidePaintingLayerTreeHostContextTest
1407 : public LayerTreeHostContextTest {
1408 public:
1409 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1410 settings->impl_side_painting = true;
1414 class LayerTreeHostContextTestImplSidePainting
1415 : public ImplSidePaintingLayerTreeHostContextTest {
1416 public:
1417 virtual void SetupTree() OVERRIDE {
1418 scoped_refptr<Layer> root = Layer::Create();
1419 root->SetBounds(gfx::Size(10, 10));
1420 root->SetAnchorPoint(gfx::PointF());
1421 root->SetIsDrawable(true);
1423 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
1424 picture->SetBounds(gfx::Size(10, 10));
1425 picture->SetAnchorPoint(gfx::PointF());
1426 picture->SetIsDrawable(true);
1427 root->AddChild(picture);
1429 layer_tree_host()->SetRootLayer(root);
1430 LayerTreeHostContextTest::SetupTree();
1433 virtual void BeginTest() OVERRIDE {
1434 times_to_lose_during_commit_ = 1;
1435 PostSetNeedsCommitToMainThread();
1438 virtual void AfterTest() OVERRIDE {}
1440 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
1441 EXPECT_TRUE(succeeded);
1442 EndTest();
1445 private:
1446 FakeContentLayerClient client_;
1449 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
1451 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1452 public:
1453 ScrollbarLayerLostContext() : commits_(0) {}
1455 virtual void BeginTest() OVERRIDE {
1456 scoped_refptr<Layer> scroll_layer = Layer::Create();
1457 scrollbar_layer_ =
1458 FakePaintedScrollbarLayer::Create(false, true, scroll_layer->id());
1459 scrollbar_layer_->SetBounds(gfx::Size(10, 100));
1460 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
1461 layer_tree_host()->root_layer()->AddChild(scroll_layer);
1462 PostSetNeedsCommitToMainThread();
1465 virtual void AfterTest() OVERRIDE {}
1467 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1468 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1470 ++commits_;
1471 switch (commits_) {
1472 case 1:
1473 // First (regular) update, we should upload 2 resources (thumb, and
1474 // backtrack).
1475 EXPECT_EQ(1, scrollbar_layer_->update_count());
1476 LoseContext();
1477 break;
1478 case 2:
1479 // Second update, after the lost context, we should still upload 2
1480 // resources even if the contents haven't changed.
1481 EXPECT_EQ(2, scrollbar_layer_->update_count());
1482 EndTest();
1483 break;
1484 case 3:
1485 // Single thread proxy issues extra commits after context lost.
1486 // http://crbug.com/287250
1487 if (HasImplThread())
1488 NOTREACHED();
1489 break;
1490 default:
1491 NOTREACHED();
1495 private:
1496 int commits_;
1497 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
1500 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1502 class UIResourceLostTest : public LayerTreeHostContextTest {
1503 public:
1504 UIResourceLostTest() : time_step_(0) {}
1505 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1506 settings->texture_id_allocation_chunk_size = 1;
1508 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1509 virtual void AfterTest() OVERRIDE {}
1511 // This is called on the main thread after each commit and
1512 // DidActivateTreeOnThread, with the value of time_step_ at the time
1513 // of the call to DidActivateTreeOnThread. Similar tests will do
1514 // work on the main thread in DidCommit but that is unsuitable because
1515 // the main thread work for these tests must happen after
1516 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1517 // painting.
1518 virtual void StepCompleteOnMainThread(int time_step) = 0;
1520 // Called after DidActivateTreeOnThread. If this is done during the commit,
1521 // the call to StepCompleteOnMainThread will not occur until after
1522 // the commit completes, because the main thread is blocked.
1523 void PostStepCompleteToMainThread() {
1524 proxy()->MainThreadTaskRunner()->PostTask(
1525 FROM_HERE,
1526 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal,
1527 base::Unretained(this),
1528 time_step_));
1531 void PostLoseContextToImplThread() {
1532 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1533 base::SingleThreadTaskRunner* task_runner =
1534 HasImplThread() ? ImplThreadTaskRunner()
1535 : base::MessageLoopProxy::current();
1536 task_runner->PostTask(FROM_HERE,
1537 base::Bind(&LayerTreeHostContextTest::LoseContext,
1538 base::Unretained(this)));
1541 protected:
1542 int time_step_;
1543 scoped_ptr<FakeScopedUIResource> ui_resource_;
1545 private:
1546 void StepCompleteOnMainThreadInternal(int step) {
1547 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1548 StepCompleteOnMainThread(step);
1552 class UIResourceLostTestSimple : public UIResourceLostTest {
1553 public:
1554 // This is called when the commit is complete and the new layer tree has been
1555 // activated.
1556 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1558 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1559 if (!layer_tree_host()->settings().impl_side_painting) {
1560 StepCompleteOnImplThread(impl);
1561 PostStepCompleteToMainThread();
1562 ++time_step_;
1566 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1567 if (layer_tree_host()->settings().impl_side_painting) {
1568 StepCompleteOnImplThread(impl);
1569 PostStepCompleteToMainThread();
1570 ++time_step_;
1575 // Losing context after an UI resource has been created.
1576 class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
1577 public:
1578 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1579 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1580 switch (step) {
1581 case 0:
1582 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1583 // Expects a valid UIResourceId.
1584 EXPECT_NE(0, ui_resource_->id());
1585 PostSetNeedsCommitToMainThread();
1586 break;
1587 case 4:
1588 // Release resource before ending the test.
1589 ui_resource_.reset();
1590 EndTest();
1591 break;
1592 case 5:
1593 // Single thread proxy issues extra commits after context lost.
1594 // http://crbug.com/287250
1595 if (HasImplThread())
1596 NOTREACHED();
1597 break;
1598 case 6:
1599 NOTREACHED();
1603 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1604 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1605 switch (time_step_) {
1606 case 1:
1607 // The resource should have been created on LTHI after the commit.
1608 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1609 PostSetNeedsCommitToMainThread();
1610 break;
1611 case 2:
1612 LoseContext();
1613 break;
1614 case 3:
1615 // The resources should have been recreated. The bitmap callback should
1616 // have been called once with the resource_lost flag set to true.
1617 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1618 // Resource Id on the impl-side have been recreated as well. Note
1619 // that the same UIResourceId persists after the context lost.
1620 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1621 PostSetNeedsCommitToMainThread();
1622 break;
1627 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
1629 // Losing context before UI resource requests can be commited. Three sequences
1630 // of creation/deletion are considered:
1631 // 1. Create one resource -> Context Lost => Expect the resource to have been
1632 // created.
1633 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1634 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1635 // test_id1_ to have been created.
1636 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1637 // the resource to not exist in the manager.
1638 class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
1639 public:
1640 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1642 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1643 switch (step) {
1644 case 0:
1645 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1646 // Lose the context on the impl thread before the commit.
1647 PostLoseContextToImplThread();
1648 break;
1649 case 2:
1650 // Sequence 2:
1651 // Currently one resource has been created.
1652 test_id0_ = ui_resource_->id();
1653 // Delete this resource.
1654 ui_resource_.reset();
1655 // Create another resource.
1656 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1657 test_id1_ = ui_resource_->id();
1658 // Sanity check that two resource creations return different ids.
1659 EXPECT_NE(test_id0_, test_id1_);
1660 // Lose the context on the impl thread before the commit.
1661 PostLoseContextToImplThread();
1662 break;
1663 case 3:
1664 // Clear the manager of resources.
1665 ui_resource_.reset();
1666 PostSetNeedsCommitToMainThread();
1667 break;
1668 case 4:
1669 // Sequence 3:
1670 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1671 test_id0_ = ui_resource_->id();
1672 // Sanity check the UIResourceId should not be 0.
1673 EXPECT_NE(0, test_id0_);
1674 // Usually ScopedUIResource are deleted from the manager in their
1675 // destructor (so usually ui_resource_.reset()). But here we need
1676 // ui_resource_ for the next step, so call DeleteUIResource directly.
1677 layer_tree_host()->DeleteUIResource(test_id0_);
1678 // Delete the resouce and then lose the context.
1679 PostLoseContextToImplThread();
1680 break;
1681 case 5:
1682 // Release resource before ending the test.
1683 ui_resource_.reset();
1684 EndTest();
1685 break;
1686 case 6:
1687 // Single thread proxy issues extra commits after context lost.
1688 // http://crbug.com/287250
1689 if (HasImplThread())
1690 NOTREACHED();
1691 break;
1692 case 8:
1693 NOTREACHED();
1697 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1698 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1699 switch (time_step_) {
1700 case 1:
1701 // Sequence 1 (continued):
1702 // The first context lost happens before the resources were created,
1703 // and because it resulted in no resources being destroyed, it does not
1704 // trigger resource re-creation.
1705 EXPECT_EQ(1, ui_resource_->resource_create_count);
1706 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1707 // Resource Id on the impl-side has been created.
1708 PostSetNeedsCommitToMainThread();
1709 break;
1710 case 3:
1711 // Sequence 2 (continued):
1712 // The previous resource should have been deleted.
1713 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1714 if (HasImplThread()) {
1715 // The second resource should have been created.
1716 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
1717 } else {
1718 // The extra commit that happens at context lost in the single thread
1719 // proxy changes the timing so that the resource has been destroyed.
1720 // http://crbug.com/287250
1721 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id1_));
1723 // The second resource called the resource callback once and since the
1724 // context is lost, a "resource lost" callback was also issued.
1725 EXPECT_EQ(2, ui_resource_->resource_create_count);
1726 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1727 break;
1728 case 5:
1729 // Sequence 3 (continued):
1730 // Expect the resource callback to have been called once.
1731 EXPECT_EQ(1, ui_resource_->resource_create_count);
1732 // No "resource lost" callbacks.
1733 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1734 // The UI resource id should not be valid
1735 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1736 break;
1740 private:
1741 UIResourceId test_id0_;
1742 UIResourceId test_id1_;
1745 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
1747 // Losing UI resource before the pending trees is activated but after the
1748 // commit. Impl-side-painting only.
1749 class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
1750 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1751 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1752 switch (step) {
1753 case 0:
1754 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1755 PostSetNeedsCommitToMainThread();
1756 break;
1757 case 3:
1758 test_id_ = ui_resource_->id();
1759 ui_resource_.reset();
1760 PostSetNeedsCommitToMainThread();
1761 break;
1762 case 5:
1763 // Release resource before ending the test.
1764 ui_resource_.reset();
1765 EndTest();
1766 break;
1767 case 6:
1768 // Make sure no extra commits happened.
1769 NOTREACHED();
1773 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1774 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1775 switch (time_step_) {
1776 case 2:
1777 PostSetNeedsCommitToMainThread();
1778 break;
1779 case 4:
1780 PostSetNeedsCommitToMainThread();
1781 break;
1785 virtual void WillActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1786 switch (time_step_) {
1787 case 1:
1788 // The resource creation callback has been called.
1789 EXPECT_EQ(1, ui_resource_->resource_create_count);
1790 // The resource is not yet lost (sanity check).
1791 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1792 // The resource should not have been created yet on the impl-side.
1793 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1794 LoseContext();
1795 break;
1796 case 3:
1797 LoseContext();
1798 break;
1802 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1803 LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1804 switch (time_step_) {
1805 case 1:
1806 // The pending requests on the impl-side should have been processed.
1807 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1808 break;
1809 case 2:
1810 // The "lost resource" callback should have been called once.
1811 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1812 break;
1813 case 4:
1814 // The resource is deleted and should not be in the manager. Use
1815 // test_id_ since ui_resource_ has been deleted.
1816 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
1817 break;
1820 PostStepCompleteToMainThread();
1821 ++time_step_;
1824 private:
1825 UIResourceId test_id_;
1828 TEST_F(UIResourceLostBeforeActivateTree,
1829 RunMultiThread_DirectRenderer_ImplSidePaint) {
1830 RunTest(true, false, true);
1833 TEST_F(UIResourceLostBeforeActivateTree,
1834 RunMultiThread_DelegatingRenderer_ImplSidePaint) {
1835 RunTest(true, true, true);
1838 // Resources evicted explicitly and by visibility changes.
1839 class UIResourceLostEviction : public UIResourceLostTestSimple {
1840 public:
1841 virtual void StepCompleteOnMainThread(int step) OVERRIDE {
1842 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1843 switch (step) {
1844 case 0:
1845 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1846 EXPECT_NE(0, ui_resource_->id());
1847 PostSetNeedsCommitToMainThread();
1848 break;
1849 case 2:
1850 // Make the tree not visible.
1851 PostSetVisibleToMainThread(false);
1852 break;
1853 case 3:
1854 // Release resource before ending the test.
1855 ui_resource_.reset();
1856 EndTest();
1857 break;
1858 case 4:
1859 NOTREACHED();
1863 virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl,
1864 bool visible) OVERRIDE {
1865 TestWebGraphicsContext3D* context = TestContext();
1866 if (!visible) {
1867 // All resources should have been evicted.
1868 ASSERT_EQ(0u, context->NumTextures());
1869 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1870 EXPECT_EQ(2, ui_resource_->resource_create_count);
1871 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1872 // Drawing is disabled both because of the evicted resources and
1873 // because the renderer is not visible.
1874 EXPECT_FALSE(impl->CanDraw());
1875 // Make the renderer visible again.
1876 PostSetVisibleToMainThread(true);
1880 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) OVERRIDE {
1881 TestWebGraphicsContext3D* context = TestContext();
1882 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1883 switch (time_step_) {
1884 case 1:
1885 // The resource should have been created on LTHI after the commit.
1886 ASSERT_EQ(1u, context->NumTextures());
1887 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1888 EXPECT_EQ(1, ui_resource_->resource_create_count);
1889 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1890 EXPECT_TRUE(impl->CanDraw());
1891 // Evict all UI resources. This will trigger a commit.
1892 impl->EvictAllUIResources();
1893 ASSERT_EQ(0u, context->NumTextures());
1894 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1895 EXPECT_EQ(1, ui_resource_->resource_create_count);
1896 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1897 EXPECT_FALSE(impl->CanDraw());
1898 break;
1899 case 2:
1900 // The resource should have been recreated.
1901 ASSERT_EQ(1u, context->NumTextures());
1902 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1903 EXPECT_EQ(2, ui_resource_->resource_create_count);
1904 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1905 EXPECT_TRUE(impl->CanDraw());
1906 break;
1907 case 3:
1908 // The resource should have been recreated after visibility was
1909 // restored.
1910 ASSERT_EQ(1u, context->NumTextures());
1911 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1912 EXPECT_EQ(3, ui_resource_->resource_create_count);
1913 EXPECT_EQ(2, ui_resource_->lost_resource_count);
1914 EXPECT_TRUE(impl->CanDraw());
1915 break;
1920 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1922 class LayerTreeHostContextTestSurfaceCreateCallback
1923 : public LayerTreeHostContextTest {
1924 public:
1925 LayerTreeHostContextTestSurfaceCreateCallback()
1926 : LayerTreeHostContextTest(),
1927 layer_(FakeContentLayer::Create(&client_)) {}
1929 virtual void SetupTree() OVERRIDE {
1930 layer_->SetBounds(gfx::Size(10, 20));
1931 layer_tree_host()->SetRootLayer(layer_);
1932 LayerTreeHostContextTest::SetupTree();
1935 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1937 virtual void DidCommit() OVERRIDE {
1938 switch (layer_tree_host()->source_frame_number()) {
1939 case 1:
1940 EXPECT_EQ(1u, layer_->output_surface_created_count());
1941 layer_tree_host()->SetNeedsCommit();
1942 break;
1943 case 2:
1944 EXPECT_EQ(1u, layer_->output_surface_created_count());
1945 layer_tree_host()->SetNeedsCommit();
1946 break;
1947 case 3:
1948 EXPECT_EQ(1u, layer_->output_surface_created_count());
1949 break;
1950 case 4:
1951 EXPECT_EQ(2u, layer_->output_surface_created_count());
1952 layer_tree_host()->SetNeedsCommit();
1953 break;
1957 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1958 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1959 switch (LastCommittedSourceFrameNumber(impl)) {
1960 case 0:
1961 break;
1962 case 1:
1963 break;
1964 case 2:
1965 LoseContext();
1966 break;
1967 case 3:
1968 EndTest();
1969 break;
1973 virtual void DidInitializeOutputSurface(bool succeeded) OVERRIDE {
1974 EXPECT_TRUE(succeeded);
1977 virtual void AfterTest() OVERRIDE {}
1979 protected:
1980 FakeContentLayerClient client_;
1981 scoped_refptr<FakeContentLayer> layer_;
1984 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
1986 } // namespace
1987 } // namespace cc