Fix revert "[chromeos] Remove dependencies of StatisticsProvider on chrome."
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest_context.cc
blob1c3da6120382c940a80e1fc96f01d9b3640fb761
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/base/thread_impl.h"
9 #include "cc/layers/content_layer.h"
10 #include "cc/layers/heads_up_display_layer.h"
11 #include "cc/layers/io_surface_layer.h"
12 #include "cc/layers/layer_impl.h"
13 #include "cc/layers/picture_layer.h"
14 #include "cc/layers/scrollbar_layer.h"
15 #include "cc/layers/texture_layer.h"
16 #include "cc/layers/video_layer.h"
17 #include "cc/layers/video_layer_impl.h"
18 #include "cc/test/fake_content_layer.h"
19 #include "cc/test/fake_content_layer_client.h"
20 #include "cc/test/fake_content_layer_impl.h"
21 #include "cc/test/fake_context_provider.h"
22 #include "cc/test/fake_delegated_renderer_layer.h"
23 #include "cc/test/fake_delegated_renderer_layer_impl.h"
24 #include "cc/test/fake_layer_tree_host_client.h"
25 #include "cc/test/fake_output_surface.h"
26 #include "cc/test/fake_scrollbar_layer.h"
27 #include "cc/test/fake_scrollbar_theme_painter.h"
28 #include "cc/test/fake_video_frame_provider.h"
29 #include "cc/test/fake_web_scrollbar.h"
30 #include "cc/test/fake_web_scrollbar_theme_geometry.h"
31 #include "cc/test/layer_tree_test.h"
32 #include "cc/test/render_pass_test_common.h"
33 #include "cc/test/test_web_graphics_context_3d.h"
34 #include "cc/trees/layer_tree_host_impl.h"
35 #include "cc/trees/layer_tree_impl.h"
36 #include "cc/trees/single_thread_proxy.h"
37 #include "gpu/GLES2/gl2extchromium.h"
38 #include "media/base/media.h"
39 #include "third_party/WebKit/Source/Platform/chromium/public/WebFilterOperations.h"
41 using media::VideoFrame;
42 using WebKit::WebGraphicsContext3D;
44 namespace cc {
45 namespace {
47 // These tests deal with losing the 3d graphics context.
48 class LayerTreeHostContextTest : public LayerTreeTest {
49 public:
50 LayerTreeHostContextTest()
51 : LayerTreeTest(),
52 context3d_(NULL),
53 times_to_fail_create_(0),
54 times_to_fail_initialize_(0),
55 times_to_lose_on_create_(0),
56 times_to_lose_during_commit_(0),
57 times_to_lose_during_draw_(0),
58 times_to_fail_recreate_(0),
59 times_to_fail_reinitialize_(0),
60 times_to_lose_on_recreate_(0),
61 times_to_fail_create_offscreen_(0),
62 times_to_fail_recreate_offscreen_(0),
63 times_to_expect_create_failed_(0),
64 times_create_failed_(0),
65 times_offscreen_created_(0),
66 committed_at_least_once_(false),
67 context_should_support_io_surface_(false) {
68 media::InitializeMediaLibraryForTesting();
71 void LoseContext() {
72 context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
73 GL_INNOCENT_CONTEXT_RESET_ARB);
74 context3d_ = NULL;
77 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
78 return TestWebGraphicsContext3D::Create();
81 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
82 if (times_to_fail_create_) {
83 --times_to_fail_create_;
84 ExpectCreateToFail();
85 return scoped_ptr<OutputSurface>();
88 scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
89 context3d_ = context3d.get();
91 if (context_should_support_io_surface_) {
92 context3d_->set_have_extension_io_surface(true);
93 context3d_->set_have_extension_egl_image(true);
96 if (times_to_fail_initialize_) {
97 --times_to_fail_initialize_;
98 // Make the context get lost during reinitialization.
99 // The number of times MakeCurrent succeeds is not important, and
100 // can be changed if needed to make this pass with future changes.
101 context3d_->set_times_make_current_succeeds(2);
102 ExpectCreateToFail();
103 } else if (times_to_lose_on_create_) {
104 --times_to_lose_on_create_;
105 LoseContext();
106 ExpectCreateToFail();
109 return FakeOutputSurface::Create3d(
110 context3d.PassAs<WebGraphicsContext3D>()).PassAs<OutputSurface>();
113 scoped_ptr<TestWebGraphicsContext3D> CreateOffscreenContext3d() {
114 if (!context3d_)
115 return scoped_ptr<TestWebGraphicsContext3D>();
117 ++times_offscreen_created_;
119 if (times_to_fail_create_offscreen_) {
120 --times_to_fail_create_offscreen_;
121 ExpectCreateToFail();
122 return scoped_ptr<TestWebGraphicsContext3D>();
125 scoped_ptr<TestWebGraphicsContext3D> offscreen_context3d =
126 TestWebGraphicsContext3D::Create().Pass();
127 DCHECK(offscreen_context3d);
128 context3d_->add_share_group_context(offscreen_context3d.get());
130 return offscreen_context3d.Pass();
133 virtual scoped_refptr<cc::ContextProvider>
134 OffscreenContextProviderForMainThread() OVERRIDE {
135 DCHECK(!ImplThread());
137 if (!offscreen_contexts_main_thread_ ||
138 offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
139 offscreen_contexts_main_thread_ = FakeContextProvider::Create(
140 base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
141 base::Unretained(this)));
142 if (offscreen_contexts_main_thread_ &&
143 !offscreen_contexts_main_thread_->BindToCurrentThread())
144 offscreen_contexts_main_thread_ = NULL;
146 return offscreen_contexts_main_thread_;
149 virtual scoped_refptr<cc::ContextProvider>
150 OffscreenContextProviderForCompositorThread() OVERRIDE {
151 DCHECK(ImplThread());
153 if (!offscreen_contexts_compositor_thread_ ||
154 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
155 offscreen_contexts_compositor_thread_ = FakeContextProvider::Create(
156 base::Bind(&LayerTreeHostContextTest::CreateOffscreenContext3d,
157 base::Unretained(this)));
159 return offscreen_contexts_compositor_thread_;
162 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
163 LayerTreeHostImpl::FrameData* frame,
164 bool result) OVERRIDE {
165 EXPECT_TRUE(result);
166 if (!times_to_lose_during_draw_)
167 return result;
169 --times_to_lose_during_draw_;
170 context3d_->set_times_make_current_succeeds(0);
172 times_to_fail_create_ = times_to_fail_recreate_;
173 times_to_fail_recreate_ = 0;
174 times_to_fail_initialize_ = times_to_fail_reinitialize_;
175 times_to_fail_reinitialize_ = 0;
176 times_to_lose_on_create_ = times_to_lose_on_recreate_;
177 times_to_lose_on_recreate_ = 0;
178 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
179 times_to_fail_recreate_offscreen_ = 0;
181 return result;
184 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
185 committed_at_least_once_ = true;
187 if (!times_to_lose_during_commit_)
188 return;
189 --times_to_lose_during_commit_;
190 LoseContext();
192 times_to_fail_create_ = times_to_fail_recreate_;
193 times_to_fail_recreate_ = 0;
194 times_to_fail_initialize_ = times_to_fail_reinitialize_;
195 times_to_fail_reinitialize_ = 0;
196 times_to_lose_on_create_ = times_to_lose_on_recreate_;
197 times_to_lose_on_recreate_ = 0;
198 times_to_fail_create_offscreen_ = times_to_fail_recreate_offscreen_;
199 times_to_fail_recreate_offscreen_ = 0;
202 virtual void DidFailToInitializeOutputSurface() OVERRIDE {
203 ++times_create_failed_;
206 virtual void TearDown() OVERRIDE {
207 LayerTreeTest::TearDown();
208 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
211 void ExpectCreateToFail() {
212 ++times_to_expect_create_failed_;
215 protected:
216 TestWebGraphicsContext3D* context3d_;
217 int times_to_fail_create_;
218 int times_to_fail_initialize_;
219 int times_to_lose_on_create_;
220 int times_to_lose_during_commit_;
221 int times_to_lose_during_draw_;
222 int times_to_fail_recreate_;
223 int times_to_fail_reinitialize_;
224 int times_to_lose_on_recreate_;
225 int times_to_fail_create_offscreen_;
226 int times_to_fail_recreate_offscreen_;
227 int times_to_expect_create_failed_;
228 int times_create_failed_;
229 int times_offscreen_created_;
230 bool committed_at_least_once_;
231 bool context_should_support_io_surface_;
233 scoped_refptr<FakeContextProvider> offscreen_contexts_main_thread_;
234 scoped_refptr<FakeContextProvider> offscreen_contexts_compositor_thread_;
237 class LayerTreeHostContextTestLostContextSucceeds
238 : public LayerTreeHostContextTest {
239 public:
240 LayerTreeHostContextTestLostContextSucceeds()
241 : LayerTreeHostContextTest(),
242 test_case_(0),
243 num_losses_(0),
244 recovered_context_(true),
245 first_initialized_(false) {}
247 virtual void BeginTest() OVERRIDE {
248 PostSetNeedsCommitToMainThread();
251 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
252 EXPECT_TRUE(succeeded);
254 if (first_initialized_)
255 ++num_losses_;
256 else
257 first_initialized_ = true;
259 recovered_context_ = true;
262 virtual void AfterTest() OVERRIDE {
263 EXPECT_EQ(10u, test_case_);
264 EXPECT_EQ(8 + 10 + 10, num_losses_);
267 virtual void DidCommitAndDrawFrame() OVERRIDE {
268 // If the last frame had a context loss, then we'll commit again to
269 // recover.
270 if (!recovered_context_)
271 return;
272 if (times_to_lose_during_commit_)
273 return;
274 if (times_to_lose_during_draw_)
275 return;
277 recovered_context_ = false;
278 if (NextTestCase())
279 InvalidateAndSetNeedsCommit();
280 else
281 EndTest();
284 virtual void InvalidateAndSetNeedsCommit() {
285 // Cause damage so we try to draw.
286 layer_tree_host()->root_layer()->SetNeedsDisplay();
289 bool NextTestCase() {
290 static const TestCase kTests[] = {
291 // Losing the context and failing to recreate it (or losing it again
292 // immediately) a small number of times should succeed.
293 { 1, // times_to_lose_during_commit
294 0, // times_to_lose_during_draw
295 3, // times_to_fail_reinitialize
296 0, // times_to_fail_recreate
297 0, // times_to_lose_on_recreate
298 0, // times_to_fail_recreate_offscreen
300 { 0, // times_to_lose_during_commit
301 1, // times_to_lose_during_draw
302 3, // times_to_fail_reinitialize
303 0, // times_to_fail_recreate
304 0, // times_to_lose_on_recreate
305 0, // times_to_fail_recreate_offscreen
307 { 1, // times_to_lose_during_commit
308 0, // times_to_lose_during_draw
309 0, // times_to_fail_reinitialize
310 3, // times_to_fail_recreate
311 0, // times_to_lose_on_recreate
312 0, // times_to_fail_recreate_offscreen
314 { 0, // times_to_lose_during_commit
315 1, // times_to_lose_during_draw
316 0, // times_to_fail_reinitialize
317 3, // times_to_fail_recreate
318 0, // times_to_lose_on_recreate
319 0, // times_to_fail_recreate_offscreen
321 { 1, // times_to_lose_during_commit
322 0, // times_to_lose_during_draw
323 0, // times_to_fail_reinitialize
324 0, // times_to_fail_recreate
325 3, // times_to_lose_on_recreate
326 0, // times_to_fail_recreate_offscreen
328 { 0, // times_to_lose_during_commit
329 1, // times_to_lose_during_draw
330 0, // times_to_fail_reinitialize
331 0, // times_to_fail_recreate
332 3, // times_to_lose_on_recreate
333 0, // times_to_fail_recreate_offscreen
335 { 1, // times_to_lose_during_commit
336 0, // times_to_lose_during_draw
337 0, // times_to_fail_reinitialize
338 0, // times_to_fail_recreate
339 0, // times_to_lose_on_recreate
340 3, // times_to_fail_recreate_offscreen
342 { 0, // times_to_lose_during_commit
343 1, // times_to_lose_during_draw
344 0, // times_to_fail_reinitialize
345 0, // times_to_fail_recreate
346 0, // times_to_lose_on_recreate
347 3, // times_to_fail_recreate_offscreen
349 // Losing the context and recreating it any number of times should
350 // succeed.
351 { 10, // times_to_lose_during_commit
352 0, // times_to_lose_during_draw
353 0, // times_to_fail_reinitialize
354 0, // times_to_fail_recreate
355 0, // times_to_lose_on_recreate
356 0, // times_to_fail_recreate_offscreen
358 { 0, // times_to_lose_during_commit
359 10, // times_to_lose_during_draw
360 0, // times_to_fail_reinitialize
361 0, // times_to_fail_recreate
362 0, // times_to_lose_on_recreate
363 0, // times_to_fail_recreate_offscreen
367 if (test_case_ >= arraysize(kTests))
368 return false;
370 times_to_lose_during_commit_ =
371 kTests[test_case_].times_to_lose_during_commit;
372 times_to_lose_during_draw_ =
373 kTests[test_case_].times_to_lose_during_draw;
374 times_to_fail_reinitialize_ = kTests[test_case_].times_to_fail_reinitialize;
375 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
376 times_to_lose_on_recreate_ = kTests[test_case_].times_to_lose_on_recreate;
377 times_to_fail_recreate_offscreen_ =
378 kTests[test_case_].times_to_fail_recreate_offscreen;
379 ++test_case_;
380 return true;
383 struct TestCase {
384 int times_to_lose_during_commit;
385 int times_to_lose_during_draw;
386 int times_to_fail_reinitialize;
387 int times_to_fail_recreate;
388 int times_to_lose_on_recreate;
389 int times_to_fail_recreate_offscreen;
392 protected:
393 size_t test_case_;
394 int num_losses_;
395 bool recovered_context_;
396 bool first_initialized_;
399 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
401 class LayerTreeHostContextTestLostContextSucceedsWithContent
402 : public LayerTreeHostContextTestLostContextSucceeds {
403 public:
404 LayerTreeHostContextTestLostContextSucceedsWithContent()
405 : LayerTreeHostContextTestLostContextSucceeds() {}
407 virtual void SetupTree() OVERRIDE {
408 root_ = Layer::Create();
409 root_->SetBounds(gfx::Size(10, 10));
410 root_->SetAnchorPoint(gfx::PointF());
411 root_->SetIsDrawable(true);
413 content_ = FakeContentLayer::Create(&client_);
414 content_->SetBounds(gfx::Size(10, 10));
415 content_->SetAnchorPoint(gfx::PointF());
416 content_->SetIsDrawable(true);
417 if (use_surface_) {
418 content_->SetForceRenderSurface(true);
419 // Filters require us to create an offscreen context.
420 WebKit::WebFilterOperations filters;
421 filters.append(WebKit::WebFilterOperation::createGrayscaleFilter(0.5f));
422 content_->SetFilters(filters);
423 content_->SetBackgroundFilters(filters);
426 root_->AddChild(content_);
428 layer_tree_host()->SetRootLayer(root_);
429 LayerTreeHostContextTest::SetupTree();
432 virtual void InvalidateAndSetNeedsCommit() OVERRIDE {
433 // Invalidate the render surface so we don't try to use a cached copy of the
434 // surface. We want to make sure to test the drawing paths for drawing to
435 // a child surface.
436 content_->SetNeedsDisplay();
437 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
440 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
441 FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>(
442 host_impl->active_tree()->root_layer()->children()[0]);
443 // Even though the context was lost, we should have a resource. The
444 // TestWebGraphicsContext3D ensures that this resource is created with
445 // the active context.
446 EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
448 cc::ContextProvider* contexts =
449 host_impl->resource_provider()->offscreen_context_provider();
450 if (use_surface_) {
451 EXPECT_TRUE(contexts->Context3d());
452 // TODO(danakj): Make a fake GrContext.
453 // EXPECT_TRUE(contexts->GrContext());
454 } else {
455 EXPECT_FALSE(contexts);
459 virtual void AfterTest() OVERRIDE {
460 LayerTreeHostContextTestLostContextSucceeds::AfterTest();
461 if (use_surface_) {
462 // 1 create to start with +
463 // 6 from test cases that fail on initializing the renderer (after the
464 // offscreen context is created) +
465 // 6 from test cases that lose the offscreen context directly +
466 // All the test cases that recreate both contexts only once
467 // per time it is lost.
468 EXPECT_EQ(6 + 6 + 1 + num_losses_, times_offscreen_created_);
469 } else {
470 EXPECT_EQ(0, times_offscreen_created_);
474 protected:
475 bool use_surface_;
476 FakeContentLayerClient client_;
477 scoped_refptr<Layer> root_;
478 scoped_refptr<ContentLayer> content_;
481 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
482 NoSurface_SingleThread) {
483 use_surface_ = false;
484 RunTest(false);
487 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
488 NoSurface_MultiThread) {
489 use_surface_ = false;
490 RunTest(true);
493 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
494 WithSurface_SingleThread) {
495 use_surface_ = true;
496 RunTest(false);
499 TEST_F(LayerTreeHostContextTestLostContextSucceedsWithContent,
500 WithSurface_MultiThread) {
501 use_surface_ = true;
502 RunTest(true);
505 class LayerTreeHostContextTestOffscreenContextFails
506 : public LayerTreeHostContextTest {
507 public:
508 virtual void SetupTree() OVERRIDE {
509 root_ = Layer::Create();
510 root_->SetBounds(gfx::Size(10, 10));
511 root_->SetAnchorPoint(gfx::PointF());
512 root_->SetIsDrawable(true);
514 content_ = FakeContentLayer::Create(&client_);
515 content_->SetBounds(gfx::Size(10, 10));
516 content_->SetAnchorPoint(gfx::PointF());
517 content_->SetIsDrawable(true);
518 content_->SetForceRenderSurface(true);
519 // Filters require us to create an offscreen context.
520 WebKit::WebFilterOperations filters;
521 filters.append(WebKit::WebFilterOperation::createGrayscaleFilter(0.5f));
522 content_->SetFilters(filters);
523 content_->SetBackgroundFilters(filters);
525 root_->AddChild(content_);
527 layer_tree_host()->SetRootLayer(root_);
528 LayerTreeHostContextTest::SetupTree();
531 virtual void BeginTest() OVERRIDE {
532 times_to_fail_create_offscreen_ = 1;
533 PostSetNeedsCommitToMainThread();
536 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
537 cc::ContextProvider* contexts =
538 host_impl->resource_provider()->offscreen_context_provider();
539 EXPECT_FALSE(contexts);
541 // This did not lead to create failure.
542 times_to_expect_create_failed_ = 0;
543 EndTest();
546 virtual void AfterTest() OVERRIDE {}
548 protected:
549 FakeContentLayerClient client_;
550 scoped_refptr<Layer> root_;
551 scoped_refptr<ContentLayer> content_;
554 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestOffscreenContextFails);
556 class LayerTreeHostContextTestLostContextFails
557 : public LayerTreeHostContextTest {
558 public:
559 LayerTreeHostContextTestLostContextFails()
560 : LayerTreeHostContextTest(),
561 num_commits_(0),
562 first_initialized_(false) {
563 times_to_lose_during_commit_ = 1;
566 virtual void BeginTest() OVERRIDE {
567 PostSetNeedsCommitToMainThread();
570 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
571 if (first_initialized_) {
572 EXPECT_FALSE(succeeded);
573 EndTest();
574 } else {
575 first_initialized_ = true;
579 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
580 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
582 ++num_commits_;
583 if (num_commits_ == 1) {
584 // When the context is ok, we should have these things.
585 EXPECT_TRUE(host_impl->output_surface());
586 EXPECT_TRUE(host_impl->renderer());
587 EXPECT_TRUE(host_impl->resource_provider());
588 return;
591 // When context recreation fails we shouldn't be left with any of them.
592 EXPECT_FALSE(host_impl->output_surface());
593 EXPECT_FALSE(host_impl->renderer());
594 EXPECT_FALSE(host_impl->resource_provider());
597 virtual void AfterTest() OVERRIDE {}
599 private:
600 int num_commits_;
601 bool first_initialized_;
604 TEST_F(LayerTreeHostContextTestLostContextFails,
605 FailReinitialize100_SingleThread) {
606 times_to_fail_reinitialize_ = 100;
607 times_to_fail_recreate_ = 0;
608 times_to_lose_on_recreate_ = 0;
609 RunTest(false);
612 TEST_F(LayerTreeHostContextTestLostContextFails,
613 FailReinitialize100_MultiThread) {
614 times_to_fail_reinitialize_ = 100;
615 times_to_fail_recreate_ = 0;
616 times_to_lose_on_recreate_ = 0;
617 RunTest(true);
620 TEST_F(LayerTreeHostContextTestLostContextFails,
621 FailRecreate100_SingleThread) {
622 times_to_fail_reinitialize_ = 0;
623 times_to_fail_recreate_ = 100;
624 times_to_lose_on_recreate_ = 0;
625 RunTest(false);
628 TEST_F(LayerTreeHostContextTestLostContextFails,
629 FailRecreate100_MultiThread) {
630 times_to_fail_reinitialize_ = 0;
631 times_to_fail_recreate_ = 100;
632 times_to_lose_on_recreate_ = 0;
633 RunTest(true);
636 TEST_F(LayerTreeHostContextTestLostContextFails,
637 LoseOnRecreate100_SingleThread) {
638 times_to_fail_reinitialize_ = 0;
639 times_to_fail_recreate_ = 0;
640 times_to_lose_on_recreate_ = 100;
641 RunTest(false);
644 TEST_F(LayerTreeHostContextTestLostContextFails,
645 LoseOnRecreate100_MultiThread) {
646 times_to_fail_reinitialize_ = 0;
647 times_to_fail_recreate_ = 0;
648 times_to_lose_on_recreate_ = 100;
649 RunTest(true);
652 class LayerTreeHostContextTestFinishAllRenderingAfterLoss
653 : public LayerTreeHostContextTest {
654 public:
655 virtual void BeginTest() OVERRIDE {
656 // Lose the context until the compositor gives up on it.
657 first_initialized_ = false;
658 times_to_lose_during_commit_ = 1;
659 times_to_fail_reinitialize_ = 10;
660 PostSetNeedsCommitToMainThread();
663 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
664 if (first_initialized_) {
665 EXPECT_FALSE(succeeded);
666 layer_tree_host()->FinishAllRendering();
667 EndTest();
668 } else {
669 first_initialized_ = true;
673 virtual void AfterTest() OVERRIDE {}
675 private:
676 bool first_initialized_;
679 SINGLE_AND_MULTI_THREAD_TEST_F(
680 LayerTreeHostContextTestFinishAllRenderingAfterLoss);
682 class LayerTreeHostContextTestLostContextAndEvictTextures
683 : public LayerTreeHostContextTest {
684 public:
685 LayerTreeHostContextTestLostContextAndEvictTextures()
686 : LayerTreeHostContextTest(),
687 layer_(FakeContentLayer::Create(&client_)),
688 impl_host_(0),
689 num_commits_(0) {}
691 virtual void SetupTree() OVERRIDE {
692 layer_->SetBounds(gfx::Size(10, 20));
693 layer_tree_host()->SetRootLayer(layer_);
694 LayerTreeHostContextTest::SetupTree();
697 virtual void BeginTest() OVERRIDE {
698 PostSetNeedsCommitToMainThread();
701 void PostEvictTextures() {
702 if (ImplThread()) {
703 ImplThread()->PostTask(
704 base::Bind(
705 &LayerTreeHostContextTestLostContextAndEvictTextures::
706 EvictTexturesOnImplThread,
707 base::Unretained(this)));
708 } else {
709 DebugScopedSetImplThread impl(proxy());
710 EvictTexturesOnImplThread();
714 void EvictTexturesOnImplThread() {
715 impl_host_->EnforceManagedMemoryPolicy(ManagedMemoryPolicy(0));
716 if (lose_after_evict_)
717 LoseContext();
720 virtual void DidCommitAndDrawFrame() OVERRIDE {
721 if (num_commits_ > 1)
722 return;
723 EXPECT_TRUE(layer_->HaveBackingAt(0, 0));
724 PostEvictTextures();
727 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
728 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
729 if (num_commits_ > 1)
730 return;
731 ++num_commits_;
732 if (!lose_after_evict_)
733 LoseContext();
734 impl_host_ = impl;
737 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
738 EXPECT_TRUE(succeeded);
739 EndTest();
742 virtual void AfterTest() OVERRIDE {}
744 protected:
745 bool lose_after_evict_;
746 FakeContentLayerClient client_;
747 scoped_refptr<FakeContentLayer> layer_;
748 LayerTreeHostImpl* impl_host_;
749 int num_commits_;
752 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
753 LoseAfterEvict_SingleThread) {
754 lose_after_evict_ = true;
755 RunTest(false);
758 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
759 LoseAfterEvict_MultiThread) {
760 lose_after_evict_ = true;
761 RunTest(true);
764 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
765 LoseBeforeEvict_SingleThread) {
766 lose_after_evict_ = false;
767 RunTest(false);
770 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
771 LoseBeforeEvict_MultiThread) {
772 lose_after_evict_ = false;
773 RunTest(true);
776 class LayerTreeHostContextTestLostContextWhileUpdatingResources
777 : public LayerTreeHostContextTest {
778 public:
779 LayerTreeHostContextTestLostContextWhileUpdatingResources()
780 : parent_(FakeContentLayer::Create(&client_)),
781 num_children_(50),
782 times_to_lose_on_end_query_(3) {}
784 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() OVERRIDE {
785 scoped_ptr<TestWebGraphicsContext3D> context =
786 LayerTreeHostContextTest::CreateContext3d();
787 if (times_to_lose_on_end_query_) {
788 --times_to_lose_on_end_query_;
789 context->set_times_end_query_succeeds(5);
791 return context.Pass();
794 virtual void SetupTree() OVERRIDE {
795 parent_->SetBounds(gfx::Size(num_children_, 1));
797 for (int i = 0; i < num_children_; i++) {
798 scoped_refptr<FakeContentLayer> child =
799 FakeContentLayer::Create(&client_);
800 child->SetPosition(gfx::PointF(i, 0.f));
801 child->SetBounds(gfx::Size(1, 1));
802 parent_->AddChild(child);
805 layer_tree_host()->SetRootLayer(parent_);
806 LayerTreeHostContextTest::SetupTree();
809 virtual void BeginTest() OVERRIDE {
810 PostSetNeedsCommitToMainThread();
813 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
814 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
815 EndTest();
818 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
819 EXPECT_TRUE(succeeded);
822 virtual void AfterTest() OVERRIDE {
823 EXPECT_EQ(0, times_to_lose_on_end_query_);
826 private:
827 FakeContentLayerClient client_;
828 scoped_refptr<FakeContentLayer> parent_;
829 int num_children_;
830 int times_to_lose_on_end_query_;
833 SINGLE_AND_MULTI_THREAD_TEST_F(
834 LayerTreeHostContextTestLostContextWhileUpdatingResources);
836 class LayerTreeHostContextTestLayersNotified
837 : public LayerTreeHostContextTest {
838 public:
839 LayerTreeHostContextTestLayersNotified()
840 : LayerTreeHostContextTest(),
841 num_commits_(0) {}
843 virtual void SetupTree() OVERRIDE {
844 root_ = FakeContentLayer::Create(&client_);
845 child_ = FakeContentLayer::Create(&client_);
846 grandchild_ = FakeContentLayer::Create(&client_);
848 root_->AddChild(child_);
849 child_->AddChild(grandchild_);
851 layer_tree_host()->SetRootLayer(root_);
852 LayerTreeHostContextTest::SetupTree();
855 virtual void BeginTest() OVERRIDE {
856 PostSetNeedsCommitToMainThread();
859 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
860 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
862 FakeContentLayerImpl* root = static_cast<FakeContentLayerImpl*>(
863 host_impl->active_tree()->root_layer());
864 FakeContentLayerImpl* child = static_cast<FakeContentLayerImpl*>(
865 root->children()[0]);
866 FakeContentLayerImpl* grandchild = static_cast<FakeContentLayerImpl*>(
867 child->children()[0]);
869 ++num_commits_;
870 switch (num_commits_) {
871 case 1:
872 EXPECT_EQ(0u, root->lost_output_surface_count());
873 EXPECT_EQ(0u, child->lost_output_surface_count());
874 EXPECT_EQ(0u, grandchild->lost_output_surface_count());
875 // Lose the context and struggle to recreate it.
876 LoseContext();
877 times_to_fail_create_ = 1;
878 break;
879 case 2:
880 EXPECT_EQ(1u, root->lost_output_surface_count());
881 EXPECT_EQ(1u, child->lost_output_surface_count());
882 EXPECT_EQ(1u, grandchild->lost_output_surface_count());
883 // Lose the context and again during recreate.
884 LoseContext();
885 times_to_lose_on_create_ = 1;
886 break;
887 case 3:
888 EXPECT_EQ(3u, root->lost_output_surface_count());
889 EXPECT_EQ(3u, child->lost_output_surface_count());
890 EXPECT_EQ(3u, grandchild->lost_output_surface_count());
891 // Lose the context and again during reinitialization.
892 LoseContext();
893 times_to_fail_initialize_ = 1;
894 break;
895 case 4:
896 EXPECT_EQ(5u, root->lost_output_surface_count());
897 EXPECT_EQ(5u, child->lost_output_surface_count());
898 EXPECT_EQ(5u, grandchild->lost_output_surface_count());
899 EndTest();
900 break;
901 default:
902 NOTREACHED();
906 virtual void AfterTest() OVERRIDE {}
908 private:
909 int num_commits_;
911 FakeContentLayerClient client_;
912 scoped_refptr<FakeContentLayer> root_;
913 scoped_refptr<FakeContentLayer> child_;
914 scoped_refptr<FakeContentLayer> grandchild_;
917 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
919 class LayerTreeHostContextTestDontUseLostResources
920 : public LayerTreeHostContextTest {
921 public:
922 virtual void SetupTree() OVERRIDE {
923 scoped_refptr<Layer> root_ = Layer::Create();
924 root_->SetBounds(gfx::Size(10, 10));
925 root_->SetAnchorPoint(gfx::PointF());
926 root_->SetIsDrawable(true);
928 scoped_refptr<FakeDelegatedRendererLayer> delegated_ =
929 FakeDelegatedRendererLayer::Create();
930 delegated_->SetBounds(gfx::Size(10, 10));
931 delegated_->SetAnchorPoint(gfx::PointF());
932 delegated_->SetIsDrawable(true);
933 root_->AddChild(delegated_);
935 scoped_refptr<ContentLayer> content_ = ContentLayer::Create(&client_);
936 content_->SetBounds(gfx::Size(10, 10));
937 content_->SetAnchorPoint(gfx::PointF());
938 content_->SetIsDrawable(true);
939 root_->AddChild(content_);
941 scoped_refptr<TextureLayer> texture_ = TextureLayer::Create(NULL);
942 texture_->SetBounds(gfx::Size(10, 10));
943 texture_->SetAnchorPoint(gfx::PointF());
944 texture_->SetTextureId(TestWebGraphicsContext3D::kExternalTextureId);
945 texture_->SetIsDrawable(true);
946 root_->AddChild(texture_);
948 scoped_refptr<ContentLayer> mask_ = ContentLayer::Create(&client_);
949 mask_->SetBounds(gfx::Size(10, 10));
950 mask_->SetAnchorPoint(gfx::PointF());
952 scoped_refptr<ContentLayer> content_with_mask_ =
953 ContentLayer::Create(&client_);
954 content_with_mask_->SetBounds(gfx::Size(10, 10));
955 content_with_mask_->SetAnchorPoint(gfx::PointF());
956 content_with_mask_->SetIsDrawable(true);
957 content_with_mask_->SetMaskLayer(mask_.get());
958 root_->AddChild(content_with_mask_);
960 scoped_refptr<VideoLayer> video_color_ = VideoLayer::Create(
961 &color_frame_provider_);
962 video_color_->SetBounds(gfx::Size(10, 10));
963 video_color_->SetAnchorPoint(gfx::PointF());
964 video_color_->SetIsDrawable(true);
965 root_->AddChild(video_color_);
967 scoped_refptr<VideoLayer> video_hw_ = VideoLayer::Create(
968 &hw_frame_provider_);
969 video_hw_->SetBounds(gfx::Size(10, 10));
970 video_hw_->SetAnchorPoint(gfx::PointF());
971 video_hw_->SetIsDrawable(true);
972 root_->AddChild(video_hw_);
974 scoped_refptr<VideoLayer> video_scaled_hw_ = VideoLayer::Create(
975 &scaled_hw_frame_provider_);
976 video_scaled_hw_->SetBounds(gfx::Size(10, 10));
977 video_scaled_hw_->SetAnchorPoint(gfx::PointF());
978 video_scaled_hw_->SetIsDrawable(true);
979 root_->AddChild(video_scaled_hw_);
981 scoped_refptr<IOSurfaceLayer> io_surface_ = IOSurfaceLayer::Create();
982 io_surface_->SetBounds(gfx::Size(10, 10));
983 io_surface_->SetAnchorPoint(gfx::PointF());
984 io_surface_->SetIsDrawable(true);
985 io_surface_->SetIOSurfaceProperties(1, gfx::Size(10, 10));
986 root_->AddChild(io_surface_);
988 // Enable the hud.
989 LayerTreeDebugState debug_state;
990 debug_state.show_property_changed_rects = true;
991 layer_tree_host()->SetDebugState(debug_state);
993 bool paint_scrollbar = true;
994 bool has_thumb = true;
995 scoped_refptr<ScrollbarLayer> scrollbar_ = ScrollbarLayer::Create(
996 FakeWebScrollbar::Create().PassAs<WebKit::WebScrollbar>(),
997 FakeScrollbarThemePainter::Create(paint_scrollbar)
998 .PassAs<ScrollbarThemePainter>(),
999 FakeWebScrollbarThemeGeometry::Create(has_thumb)
1000 .PassAs<WebKit::WebScrollbarThemeGeometry>(),
1001 content_->id());
1002 scrollbar_->SetBounds(gfx::Size(10, 10));
1003 scrollbar_->SetAnchorPoint(gfx::PointF());
1004 scrollbar_->SetIsDrawable(true);
1005 root_->AddChild(scrollbar_);
1007 layer_tree_host()->SetRootLayer(root_);
1008 LayerTreeHostContextTest::SetupTree();
1011 virtual void BeginTest() OVERRIDE {
1012 context_should_support_io_surface_ = true;
1013 PostSetNeedsCommitToMainThread();
1016 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1017 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
1019 ResourceProvider* resource_provider = host_impl->resource_provider();
1021 if (host_impl->active_tree()->source_frame_number() == 0) {
1022 // Set up impl resources on the first commit.
1024 scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
1025 pass_for_quad->SetNew(
1026 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
1027 RenderPass::Id(1, 1),
1028 gfx::Rect(0, 0, 10, 10),
1029 gfx::Rect(0, 0, 10, 10),
1030 gfx::Transform());
1032 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
1033 pass->SetNew(
1034 RenderPass::Id(2, 1),
1035 gfx::Rect(0, 0, 10, 10),
1036 gfx::Rect(0, 0, 10, 10),
1037 gfx::Transform());
1038 pass->AppendOneOfEveryQuadType(resource_provider, RenderPass::Id(2, 1));
1040 ScopedPtrVector<RenderPass> pass_list;
1041 pass_list.push_back(pass_for_quad.PassAs<RenderPass>());
1042 pass_list.push_back(pass.PassAs<RenderPass>());
1044 // First child is the delegated layer.
1045 FakeDelegatedRendererLayerImpl* delegated_impl =
1046 static_cast<FakeDelegatedRendererLayerImpl*>(
1047 host_impl->active_tree()->root_layer()->children()[0]);
1048 delegated_impl->SetFrameDataForRenderPasses(&pass_list);
1049 EXPECT_TRUE(pass_list.empty());
1051 color_video_frame_ = VideoFrame::CreateColorFrame(
1052 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
1053 hw_video_frame_ = VideoFrame::WrapNativeTexture(
1054 resource_provider->GraphicsContext3D()->createTexture(),
1055 GL_TEXTURE_2D,
1056 gfx::Size(4, 4), gfx::Rect(0, 0, 4, 4), gfx::Size(4, 4),
1057 base::TimeDelta(),
1058 VideoFrame::ReadPixelsCB(),
1059 base::Closure());
1060 scaled_hw_video_frame_ = VideoFrame::WrapNativeTexture(
1061 resource_provider->GraphicsContext3D()->createTexture(),
1062 GL_TEXTURE_2D,
1063 gfx::Size(4, 4), gfx::Rect(0, 0, 3, 2), gfx::Size(4, 4),
1064 base::TimeDelta(),
1065 VideoFrame::ReadPixelsCB(),
1066 base::Closure());
1068 color_frame_provider_.set_frame(color_video_frame_);
1069 hw_frame_provider_.set_frame(hw_video_frame_);
1070 scaled_hw_frame_provider_.set_frame(scaled_hw_video_frame_);
1071 return;
1074 if (host_impl->active_tree()->source_frame_number() == 3) {
1075 // On the third commit we're recovering from context loss. Hardware
1076 // video frames should not be reused by the VideoFrameProvider, but
1077 // software frames can be.
1078 hw_frame_provider_.set_frame(NULL);
1079 scaled_hw_frame_provider_.set_frame(NULL);
1083 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1084 LayerTreeHostImpl::FrameData* frame,
1085 bool result) OVERRIDE {
1086 if (host_impl->active_tree()->source_frame_number() == 2) {
1087 // Lose the context during draw on the second commit. This will cause
1088 // a third commit to recover.
1089 if (context3d_)
1090 context3d_->set_times_bind_texture_succeeds(4);
1092 return true;
1095 virtual void DidCommitAndDrawFrame() OVERRIDE {
1096 ASSERT_TRUE(layer_tree_host()->hud_layer());
1097 // End the test once we know the 3nd frame drew.
1098 if (layer_tree_host()->commit_number() == 4)
1099 EndTest();
1100 else
1101 layer_tree_host()->SetNeedsCommit();
1104 virtual void AfterTest() OVERRIDE {}
1106 private:
1107 FakeContentLayerClient client_;
1109 scoped_refptr<Layer> root_;
1110 scoped_refptr<DelegatedRendererLayer> delegated_;
1111 scoped_refptr<ContentLayer> content_;
1112 scoped_refptr<TextureLayer> texture_;
1113 scoped_refptr<ContentLayer> mask_;
1114 scoped_refptr<ContentLayer> content_with_mask_;
1115 scoped_refptr<VideoLayer> video_color_;
1116 scoped_refptr<VideoLayer> video_hw_;
1117 scoped_refptr<VideoLayer> video_scaled_hw_;
1118 scoped_refptr<IOSurfaceLayer> io_surface_;
1119 scoped_refptr<ScrollbarLayer> scrollbar_;
1121 scoped_refptr<VideoFrame> color_video_frame_;
1122 scoped_refptr<VideoFrame> hw_video_frame_;
1123 scoped_refptr<VideoFrame> scaled_hw_video_frame_;
1125 FakeVideoFrameProvider color_frame_provider_;
1126 FakeVideoFrameProvider hw_frame_provider_;
1127 FakeVideoFrameProvider scaled_hw_frame_provider_;
1130 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
1132 class LayerTreeHostContextTestLosesFirstOutputSurface
1133 : public LayerTreeHostContextTest {
1134 public:
1135 LayerTreeHostContextTestLosesFirstOutputSurface() {
1136 // Always fail. This needs to be set before LayerTreeHost is created.
1137 times_to_lose_on_create_ = 1000;
1140 virtual void BeginTest() OVERRIDE {
1141 PostSetNeedsCommitToMainThread();
1144 virtual void AfterTest() OVERRIDE {}
1146 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
1147 EXPECT_FALSE(succeeded);
1149 // If we make it this far without crashing, we pass!
1150 EndTest();
1153 virtual void DidCommitAndDrawFrame() OVERRIDE {
1154 EXPECT_TRUE(false);
1158 SINGLE_AND_MULTI_THREAD_TEST_F(
1159 LayerTreeHostContextTestLosesFirstOutputSurface);
1161 class LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds
1162 : public LayerTreeHostContextTest {
1163 public:
1164 virtual void AfterTest() OVERRIDE {}
1166 virtual void BeginTest() OVERRIDE {
1167 times_to_fail_initialize_ = 2;
1168 PostSetNeedsCommitToMainThread();
1171 virtual void DidCommitAndDrawFrame() OVERRIDE {
1172 EndTest();
1176 SINGLE_AND_MULTI_THREAD_TEST_F(
1177 LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds);
1179 class LayerTreeHostContextTestRetryWorksWithForcedInit
1180 : public LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds {
1181 public:
1182 virtual void DidFailToInitializeOutputSurface() OVERRIDE {
1183 LayerTreeHostContextTestRetriesFirstInitializationAndSucceeds
1184 ::DidFailToInitializeOutputSurface();
1186 if (times_create_failed_ == 1) {
1187 // CompositeAndReadback force recreates the output surface, which should
1188 // fail.
1189 char pixels[4];
1190 EXPECT_FALSE(layer_tree_host()->CompositeAndReadback(
1191 &pixels, gfx::Rect(1, 1)));
1196 SINGLE_AND_MULTI_THREAD_TEST_F(
1197 LayerTreeHostContextTestRetryWorksWithForcedInit);
1199 class LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit
1200 : public LayerTreeHostContextTest {
1201 public:
1202 virtual void BeginTest() OVERRIDE {
1203 // This must be called immediately after creating LTH, before the first
1204 // OutputSurface is initialized.
1205 ASSERT_TRUE(layer_tree_host()->output_surface_lost());
1207 times_output_surface_created_ = 0;
1209 char pixels[4];
1210 EXPECT_TRUE(layer_tree_host()->CompositeAndReadback(
1211 &pixels, gfx::Rect(1, 1)));
1212 EXPECT_EQ(1, times_output_surface_created_);
1214 PostSetNeedsCommitToMainThread();
1217 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
1218 EXPECT_TRUE(succeeded);
1219 ++times_output_surface_created_;
1222 virtual void DidCommitAndDrawFrame() OVERRIDE {
1223 EndTest();
1226 virtual void AfterTest() OVERRIDE {
1227 // Should not try to create output surface again after successfully
1228 // created by CompositeAndReadback.
1229 EXPECT_EQ(1, times_output_surface_created_);
1232 private:
1233 int times_output_surface_created_;
1236 SINGLE_AND_MULTI_THREAD_TEST_F(
1237 LayerTreeHostContextTestCompositeAndReadbackBeforeOutputSurfaceInit);
1239 class ImplSidePaintingLayerTreeHostContextTest
1240 : public LayerTreeHostContextTest {
1241 public:
1242 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1243 settings->impl_side_painting = true;
1247 class LayerTreeHostContextTestImplSidePainting
1248 : public ImplSidePaintingLayerTreeHostContextTest {
1249 public:
1250 virtual void SetupTree() OVERRIDE {
1251 scoped_refptr<Layer> root = Layer::Create();
1252 root->SetBounds(gfx::Size(10, 10));
1253 root->SetAnchorPoint(gfx::PointF());
1254 root->SetIsDrawable(true);
1256 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
1257 picture->SetBounds(gfx::Size(10, 10));
1258 picture->SetAnchorPoint(gfx::PointF());
1259 picture->SetIsDrawable(true);
1260 root->AddChild(picture);
1262 layer_tree_host()->SetRootLayer(root);
1263 LayerTreeHostContextTest::SetupTree();
1266 virtual void BeginTest() OVERRIDE {
1267 times_to_lose_during_commit_ = 1;
1268 PostSetNeedsCommitToMainThread();
1271 virtual void AfterTest() OVERRIDE {}
1273 virtual void DidRecreateOutputSurface(bool succeeded) OVERRIDE {
1274 EXPECT_TRUE(succeeded);
1275 EndTest();
1278 private:
1279 FakeContentLayerClient client_;
1282 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
1284 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1285 public:
1286 ScrollbarLayerLostContext() : commits_(0) {}
1288 virtual void BeginTest() OVERRIDE {
1289 scoped_refptr<Layer> scroll_layer = Layer::Create();
1290 scrollbar_layer_ = FakeScrollbarLayer::Create(
1291 false, true, scroll_layer->id());
1292 scrollbar_layer_->SetBounds(gfx::Size(10, 100));
1293 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
1294 layer_tree_host()->root_layer()->AddChild(scroll_layer);
1295 PostSetNeedsCommitToMainThread();
1298 virtual void AfterTest() OVERRIDE {}
1300 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1301 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1303 ++commits_;
1304 size_t upload_count = scrollbar_layer_->last_update_full_upload_size() +
1305 scrollbar_layer_->last_update_partial_upload_size();
1306 switch (commits_) {
1307 case 1:
1308 // First (regular) update, we should upload 2 resources (thumb, and
1309 // backtrack).
1310 EXPECT_EQ(1, scrollbar_layer_->update_count());
1311 EXPECT_EQ(2u, upload_count);
1312 LoseContext();
1313 break;
1314 case 2:
1315 // Second update, after the lost context, we should still upload 2
1316 // resources even if the contents haven't changed.
1317 EXPECT_EQ(2, scrollbar_layer_->update_count());
1318 EXPECT_EQ(2u, upload_count);
1319 EndTest();
1320 break;
1321 default:
1322 NOTREACHED();
1326 private:
1327 int commits_;
1328 scoped_refptr<FakeScrollbarLayer> scrollbar_layer_;
1331 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1333 class LayerTreeHostContextTestFailsToCreateSurface
1334 : public LayerTreeHostContextTest {
1335 public:
1336 LayerTreeHostContextTestFailsToCreateSurface()
1337 : LayerTreeHostContextTest(),
1338 failure_count_(0) {
1339 times_to_lose_on_create_ = 10;
1342 virtual void BeginTest() OVERRIDE {
1343 PostSetNeedsCommitToMainThread();
1346 virtual void AfterTest() OVERRIDE {}
1348 virtual void DidRecreateOutputSurface(bool success) OVERRIDE {
1349 EXPECT_FALSE(success);
1350 EXPECT_EQ(0, failure_count_);
1351 times_to_lose_on_create_ = 0;
1352 failure_count_++;
1353 // Normally, the embedder should stop trying to use the compositor at
1354 // this point, but let's force it back into action when we shouldn't.
1355 char pixels[4];
1356 EXPECT_FALSE(
1357 layer_tree_host()->CompositeAndReadback(pixels, gfx::Rect(1, 1)));
1358 // If we've made it this far without crashing, we've succeeded.
1359 EndTest();
1362 private:
1363 int failure_count_;
1366 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestFailsToCreateSurface);
1368 // Not reusing LayerTreeTest because it expects creating LTH to always succeed.
1369 class LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface
1370 : public testing::Test,
1371 public FakeLayerTreeHostClient {
1372 public:
1373 LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface()
1374 : FakeLayerTreeHostClient(FakeLayerTreeHostClient::DIRECT_3D) {}
1376 // FakeLayerTreeHostClient
1377 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
1378 return scoped_ptr<OutputSurface>();
1381 void RunTest(bool threaded) {
1382 scoped_ptr<base::Thread> impl_thread;
1383 scoped_ptr<cc::Thread> impl_ccthread(NULL);
1384 if (threaded) {
1385 impl_thread.reset(new base::Thread("LayerTreeTest"));
1386 impl_ccthread = cc::ThreadImpl::CreateForDifferentThread(
1387 impl_thread->message_loop_proxy());
1388 ASSERT_TRUE(impl_ccthread);
1391 LayerTreeSettings settings;
1392 scoped_ptr<LayerTreeHost> layer_tree_host =
1393 LayerTreeHost::Create(this, settings, impl_ccthread.Pass());
1394 EXPECT_FALSE(layer_tree_host);
1398 SINGLE_AND_MULTI_THREAD_TEST_F(
1399 LayerTreeHostTestCannotCreateIfCannotCreateOutputSurface);
1401 } // namespace
1402 } // namespace cc