Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: cc/trees/layer_tree_host_unittest_context.cc

Issue 1057283003: Remove parts of //cc we aren't using (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "cc/trees/layer_tree_host.h"
6
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/output/filter_operations.h"
19 #include "cc/resources/single_release_callback.h"
20 #include "cc/test/failure_output_surface.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_picture_layer.h"
31 #include "cc/test/fake_picture_layer_impl.h"
32 #include "cc/test/fake_scoped_ui_resource.h"
33 #include "cc/test/fake_scrollbar.h"
34 #include "cc/test/layer_tree_test.h"
35 #include "cc/test/render_pass_test_common.h"
36 #include "cc/test/test_context_provider.h"
37 #include "cc/test/test_shared_bitmap_manager.h"
38 #include "cc/test/test_web_graphics_context_3d.h"
39 #include "cc/trees/layer_tree_host_impl.h"
40 #include "cc/trees/layer_tree_impl.h"
41 #include "cc/trees/single_thread_proxy.h"
42 #include "gpu/GLES2/gl2extchromium.h"
43
44 namespace cc {
45 namespace {
46
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_lose_during_commit_(0),
55 times_to_lose_during_draw_(0),
56 times_to_fail_recreate_(0),
57 times_to_expect_create_failed_(0),
58 times_create_failed_(0),
59 committed_at_least_once_(false),
60 context_should_support_io_surface_(false),
61 fallback_context_works_(false),
62 async_output_surface_creation_(false) {
63 }
64
65 void LoseContext() {
66 // For sanity-checking tests, they should only call this when the
67 // context is not lost.
68 CHECK(context3d_);
69 context3d_->loseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
70 GL_INNOCENT_CONTEXT_RESET_ARB);
71 context3d_ = NULL;
72 }
73
74 virtual scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() {
75 return TestWebGraphicsContext3D::Create();
76 }
77
78 scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
79 if (times_to_fail_create_) {
80 --times_to_fail_create_;
81 ExpectCreateToFail();
82 return make_scoped_ptr(new FailureOutputSurface(delegating_renderer()));
83 }
84
85 scoped_ptr<TestWebGraphicsContext3D> context3d = CreateContext3d();
86 context3d_ = context3d.get();
87
88 if (context_should_support_io_surface_) {
89 context3d_->set_have_extension_io_surface(true);
90 context3d_->set_have_extension_egl_image(true);
91 }
92
93 if (delegating_renderer())
94 return FakeOutputSurface::CreateDelegating3d(context3d.Pass());
95 else
96 return FakeOutputSurface::Create3d(context3d.Pass());
97 }
98
99 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
100 LayerTreeHostImpl::FrameData* frame,
101 DrawResult draw_result) override {
102 if (draw_result == DRAW_ABORTED_MISSING_HIGH_RES_CONTENT) {
103 // Only valid for single-threaded impl-side painting, which activates
104 // immediately and will try to draw again when content has finished.
105 DCHECK(!host_impl->proxy()->HasImplThread());
106 DCHECK(host_impl->settings().impl_side_painting);
107 return draw_result;
108 }
109 EXPECT_EQ(DRAW_SUCCESS, draw_result);
110 if (!times_to_lose_during_draw_)
111 return draw_result;
112
113 --times_to_lose_during_draw_;
114 LoseContext();
115
116 times_to_fail_create_ = times_to_fail_recreate_;
117 times_to_fail_recreate_ = 0;
118
119 return draw_result;
120 }
121
122 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
123 committed_at_least_once_ = true;
124
125 if (!times_to_lose_during_commit_)
126 return;
127 --times_to_lose_during_commit_;
128 LoseContext();
129
130 times_to_fail_create_ = times_to_fail_recreate_;
131 times_to_fail_recreate_ = 0;
132 }
133
134 void DidFailToInitializeOutputSurface() override { ++times_create_failed_; }
135
136 void TearDown() override {
137 LayerTreeTest::TearDown();
138 EXPECT_EQ(times_to_expect_create_failed_, times_create_failed_);
139 }
140
141 void ExpectCreateToFail() { ++times_to_expect_create_failed_; }
142
143 protected:
144 TestWebGraphicsContext3D* context3d_;
145 int times_to_fail_create_;
146 int times_to_lose_during_commit_;
147 int times_to_lose_during_draw_;
148 int times_to_fail_recreate_;
149 int times_to_expect_create_failed_;
150 int times_create_failed_;
151 bool committed_at_least_once_;
152 bool context_should_support_io_surface_;
153 bool fallback_context_works_;
154 bool async_output_surface_creation_;
155 };
156
157 class LayerTreeHostContextTestLostContextSucceeds
158 : public LayerTreeHostContextTest {
159 public:
160 LayerTreeHostContextTestLostContextSucceeds()
161 : LayerTreeHostContextTest(),
162 test_case_(0),
163 num_losses_(0),
164 num_losses_last_test_case_(-1),
165 recovered_context_(true),
166 first_initialized_(false) {}
167
168 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
169
170 void RequestNewOutputSurface() override {
171 if (async_output_surface_creation_) {
172 MainThreadTaskRunner()->PostTask(
173 FROM_HERE, base::Bind(&LayerTreeHostContextTestLostContextSucceeds::
174 CreateAndSetOutputSurface,
175 base::Unretained(this)));
176 } else {
177 CreateAndSetOutputSurface();
178 }
179 }
180
181 void CreateAndSetOutputSurface() {
182 scoped_ptr<OutputSurface> surface(
183 LayerTreeHostContextTest::CreateOutputSurface());
184 CHECK(surface);
185 layer_tree_host()->SetOutputSurface(surface.Pass());
186 }
187
188 void DidInitializeOutputSurface() override {
189 if (first_initialized_)
190 ++num_losses_;
191 else
192 first_initialized_ = true;
193
194 recovered_context_ = true;
195 }
196
197 void AfterTest() override { EXPECT_EQ(11u, test_case_); }
198
199 void DidCommitAndDrawFrame() override {
200 // If the last frame had a context loss, then we'll commit again to
201 // recover.
202 if (!recovered_context_)
203 return;
204 if (times_to_lose_during_commit_)
205 return;
206 if (times_to_lose_during_draw_)
207 return;
208
209 recovered_context_ = false;
210 if (NextTestCase())
211 InvalidateAndSetNeedsCommit();
212 else
213 EndTest();
214 }
215
216 virtual void InvalidateAndSetNeedsCommit() {
217 // Cause damage so we try to draw.
218 layer_tree_host()->root_layer()->SetNeedsDisplay();
219 layer_tree_host()->SetNeedsCommit();
220 }
221
222 bool NextTestCase() {
223 static const TestCase kTests[] = {
224 // Losing the context and failing to recreate it (or losing it again
225 // immediately) a small number of times should succeed.
226 {
227 1, // times_to_lose_during_commit
228 0, // times_to_lose_during_draw
229 0, // times_to_fail_recreate
230 false, // fallback_context_works
231 false, // async_output_surface_creation
232 },
233 {
234 0, // times_to_lose_during_commit
235 1, // times_to_lose_during_draw
236 0, // times_to_fail_recreate
237 false, // fallback_context_works
238 false, // async_output_surface_creation
239 },
240 {
241 1, // times_to_lose_during_commit
242 0, // times_to_lose_during_draw
243 3, // times_to_fail_recreate
244 false, // fallback_context_works
245 false, // async_output_surface_creation
246 },
247 {
248 0, // times_to_lose_during_commit
249 1, // times_to_lose_during_draw
250 3, // times_to_fail_recreate
251 false, // fallback_context_works
252 false, // async_output_surface_creation
253 },
254 {
255 0, // times_to_lose_during_commit
256 1, // times_to_lose_during_draw
257 3, // times_to_fail_recreate
258 false, // fallback_context_works
259 true, // async_output_surface_creation
260 },
261 // Losing the context and recreating it any number of times should
262 // succeed.
263 {
264 10, // times_to_lose_during_commit
265 0, // times_to_lose_during_draw
266 0, // times_to_fail_recreate
267 false, // fallback_context_works
268 false, // async_output_surface_creation
269 },
270 {
271 0, // times_to_lose_during_commit
272 10, // times_to_lose_during_draw
273 0, // times_to_fail_recreate
274 false, // fallback_context_works
275 false, // async_output_surface_creation
276 },
277 {
278 10, // times_to_lose_during_commit
279 0, // times_to_lose_during_draw
280 0, // times_to_fail_recreate
281 false, // fallback_context_works
282 true, // async_output_surface_creation
283 },
284 {
285 0, // times_to_lose_during_commit
286 10, // times_to_lose_during_draw
287 0, // times_to_fail_recreate
288 false, // fallback_context_works
289 true, // async_output_surface_creation
290 },
291 // Losing the context, failing to reinitialize it, and making a fallback
292 // context should work.
293 {
294 0, // times_to_lose_during_commit
295 1, // times_to_lose_during_draw
296 0, // times_to_fail_recreate
297 true, // fallback_context_works
298 false, // async_output_surface_creation
299 },
300 {
301 0, // times_to_lose_during_commit
302 1, // times_to_lose_during_draw
303 0, // times_to_fail_recreate
304 true, // fallback_context_works
305 true, // async_output_surface_creation
306 },
307 };
308
309 if (test_case_ >= arraysize(kTests))
310 return false;
311 // Make sure that we lost our context at least once in the last test run so
312 // the test did something.
313 EXPECT_GT(num_losses_, num_losses_last_test_case_);
314 num_losses_last_test_case_ = num_losses_;
315
316 times_to_lose_during_commit_ =
317 kTests[test_case_].times_to_lose_during_commit;
318 times_to_lose_during_draw_ = kTests[test_case_].times_to_lose_during_draw;
319 times_to_fail_recreate_ = kTests[test_case_].times_to_fail_recreate;
320 fallback_context_works_ = kTests[test_case_].fallback_context_works;
321 async_output_surface_creation_ =
322 kTests[test_case_].async_output_surface_creation;
323 ++test_case_;
324 return true;
325 }
326
327 struct TestCase {
328 int times_to_lose_during_commit;
329 int times_to_lose_during_draw;
330 int times_to_fail_recreate;
331 bool fallback_context_works;
332 bool async_output_surface_creation;
333 };
334
335 protected:
336 size_t test_case_;
337 int num_losses_;
338 int num_losses_last_test_case_;
339 bool recovered_context_;
340 bool first_initialized_;
341 };
342
343 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLostContextSucceeds);
344
345 class LayerTreeHostClientNotReadyDoesNotCreateOutputSurface
346 : public LayerTreeHostContextTest {
347 public:
348 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface()
349 : LayerTreeHostContextTest() {}
350
351 void WillBeginTest() override {
352 // Override and do not signal SetLayerTreeHostClientReady.
353 }
354
355 void BeginTest() override {
356 PostSetNeedsCommitToMainThread();
357 EndTest();
358 }
359
360 scoped_ptr<OutputSurface> CreateOutputSurface() override {
361 EXPECT_TRUE(false);
362 return nullptr;
363 }
364
365 void DidInitializeOutputSurface() override { EXPECT_TRUE(false); }
366
367 void AfterTest() override {}
368 };
369
370 SINGLE_AND_MULTI_THREAD_TEST_F(
371 LayerTreeHostClientNotReadyDoesNotCreateOutputSurface);
372
373 class MultipleCompositeDoesNotCreateOutputSurface
374 : public LayerTreeHostContextTest {
375 public:
376 MultipleCompositeDoesNotCreateOutputSurface()
377 : LayerTreeHostContextTest(), request_count_(0) {}
378
379 void InitializeSettings(LayerTreeSettings* settings) override {
380 settings->single_thread_proxy_scheduler = false;
381 }
382
383 void RequestNewOutputSurface() override {
384 EXPECT_GE(1, ++request_count_);
385 EndTest();
386 }
387
388 void BeginTest() override {
389 layer_tree_host()->Composite(base::TimeTicks());
390 layer_tree_host()->Composite(base::TimeTicks());
391 }
392
393 scoped_ptr<OutputSurface> CreateOutputSurface() override {
394 EXPECT_TRUE(false);
395 return nullptr;
396 }
397
398 void DidInitializeOutputSurface() override { EXPECT_TRUE(false); }
399
400 void AfterTest() override {}
401
402 int request_count_;
403 };
404
405 SINGLE_THREAD_NOIMPL_TEST_F(MultipleCompositeDoesNotCreateOutputSurface);
406
407 // This test makes sure that once a SingleThreadProxy issues a
408 // DidFailToInitializeOutputSurface, that future Composite calls will not
409 // trigger additional requests for output surfaces.
410 class FailedCreateDoesNotCreateExtraOutputSurface
411 : public LayerTreeHostContextTest {
412 public:
413 FailedCreateDoesNotCreateExtraOutputSurface()
414 : LayerTreeHostContextTest(), num_requests_(0), has_failed_(false) {}
415
416 void InitializeSettings(LayerTreeSettings* settings) override {
417 settings->single_thread_proxy_scheduler = false;
418 }
419
420 void RequestNewOutputSurface() override {
421 num_requests_++;
422 // There should be one initial request and then one request from
423 // the LayerTreeTest test hooks DidFailToInitializeOutputSurface (which is
424 // hard to skip). This second request is just ignored and is test cruft.
425 EXPECT_LE(num_requests_, 2);
426 if (num_requests_ > 1)
427 return;
428 ExpectCreateToFail();
429 layer_tree_host()->SetOutputSurface(
430 make_scoped_ptr(new FailureOutputSurface(false)));
431 }
432
433 void BeginTest() override {
434 // First composite tries to create a surface.
435 layer_tree_host()->Composite(base::TimeTicks());
436 EXPECT_EQ(num_requests_, 2);
437 EXPECT_TRUE(has_failed_);
438
439 // Second composite should not request or fail.
440 layer_tree_host()->Composite(base::TimeTicks());
441 EXPECT_EQ(num_requests_, 2);
442 EndTest();
443 }
444
445 void DidInitializeOutputSurface() override { EXPECT_TRUE(false); }
446
447 void DidFailToInitializeOutputSurface() override {
448 LayerTreeHostContextTest::DidFailToInitializeOutputSurface();
449 EXPECT_FALSE(has_failed_);
450 has_failed_ = true;
451 }
452
453 void AfterTest() override {}
454
455 int num_requests_;
456 bool has_failed_;
457 };
458
459 SINGLE_THREAD_NOIMPL_TEST_F(FailedCreateDoesNotCreateExtraOutputSurface);
460
461 class LayerTreeHostContextTestCommitAfterDelayedOutputSurface
462 : public LayerTreeHostContextTest {
463 public:
464 LayerTreeHostContextTestCommitAfterDelayedOutputSurface()
465 : LayerTreeHostContextTest(), creating_output_(false) {}
466
467 void InitializeSettings(LayerTreeSettings* settings) override {
468 settings->single_thread_proxy_scheduler = false;
469 }
470
471 void RequestNewOutputSurface() override {
472 MainThreadTaskRunner()->PostTask(
473 FROM_HERE,
474 base::Bind(&LayerTreeHostContextTestCommitAfterDelayedOutputSurface::
475 CreateAndSetOutputSurface,
476 base::Unretained(this)));
477 }
478
479 void CreateAndSetOutputSurface() {
480 creating_output_ = true;
481 layer_tree_host()->SetOutputSurface(
482 LayerTreeHostContextTest::CreateOutputSurface());
483 }
484
485 void BeginTest() override { layer_tree_host()->Composite(base::TimeTicks()); }
486
487 void ScheduleComposite() override {
488 if (creating_output_)
489 EndTest();
490 }
491
492 void AfterTest() override {}
493
494 bool creating_output_;
495 };
496
497 SINGLE_THREAD_NOIMPL_TEST_F(
498 LayerTreeHostContextTestCommitAfterDelayedOutputSurface);
499
500 class LayerTreeHostContextTestAvoidUnnecessaryComposite
501 : public LayerTreeHostContextTest {
502 public:
503 LayerTreeHostContextTestAvoidUnnecessaryComposite()
504 : LayerTreeHostContextTest(), in_composite_(false) {}
505
506 void InitializeSettings(LayerTreeSettings* settings) override {
507 settings->single_thread_proxy_scheduler = false;
508 }
509
510 void RequestNewOutputSurface() override {
511 layer_tree_host()->SetOutputSurface(
512 LayerTreeHostContextTest::CreateOutputSurface());
513 EndTest();
514 }
515
516 void BeginTest() override {
517 in_composite_ = true;
518 layer_tree_host()->Composite(base::TimeTicks());
519 in_composite_ = false;
520 }
521
522 void ScheduleComposite() override { EXPECT_FALSE(in_composite_); }
523
524 void AfterTest() override {}
525
526 bool in_composite_;
527 };
528
529 SINGLE_THREAD_NOIMPL_TEST_F(LayerTreeHostContextTestAvoidUnnecessaryComposite);
530
531 class LayerTreeHostContextTestLostContextSucceedsWithContent
532 : public LayerTreeHostContextTestLostContextSucceeds {
533 public:
534 void SetupTree() override {
535 root_ = Layer::Create();
536 root_->SetBounds(gfx::Size(10, 10));
537 root_->SetIsDrawable(true);
538
539 // Paint non-solid color.
540 SkPaint paint;
541 paint.setColor(SkColorSetARGB(100, 80, 200, 200));
542 client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint);
543
544 if (layer_tree_host()->settings().impl_side_painting)
545 layer_ = FakePictureLayer::Create(&client_);
546 else
547 layer_ = FakeContentLayer::Create(&client_);
548 layer_->SetBounds(gfx::Size(10, 10));
549 layer_->SetIsDrawable(true);
550
551 root_->AddChild(layer_);
552
553 layer_tree_host()->SetRootLayer(root_);
554 LayerTreeHostContextTest::SetupTree();
555 }
556
557 void InvalidateAndSetNeedsCommit() override {
558 // Invalidate the render surface so we don't try to use a cached copy of the
559 // surface. We want to make sure to test the drawing paths for drawing to
560 // a child surface.
561 layer_->SetNeedsDisplay();
562 LayerTreeHostContextTestLostContextSucceeds::InvalidateAndSetNeedsCommit();
563 }
564
565 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
566 if (!host_impl->settings().impl_side_painting) {
567 FakeContentLayerImpl* content_impl = static_cast<FakeContentLayerImpl*>(
568 host_impl->active_tree()->root_layer()->children()[0]);
569 // Even though the context was lost, we should have a resource. The
570 // TestWebGraphicsContext3D ensures that this resource is created with
571 // the active context.
572 EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
573 } else {
574 FakePictureLayerImpl* picture_impl = static_cast<FakePictureLayerImpl*>(
575 host_impl->active_tree()->root_layer()->children()[0]);
576 EXPECT_TRUE(picture_impl->HighResTiling()->TileAt(0, 0)->IsReadyToDraw());
577 }
578 }
579
580 protected:
581 FakeContentLayerClient client_;
582 scoped_refptr<Layer> root_;
583 scoped_refptr<Layer> layer_;
584 };
585
586 // This test uses TiledLayer and PictureLayer to check for a working context.
587 SINGLE_AND_MULTI_THREAD_TEST_F(
588 LayerTreeHostContextTestLostContextSucceedsWithContent);
589
590 class LayerTreeHostContextTestCreateOutputSurfaceFailsOnce
591 : public LayerTreeHostContextTest {
592 public:
593 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce()
594 : times_to_fail_(1), times_initialized_(0) {
595 times_to_fail_create_ = times_to_fail_;
596 }
597
598 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
599
600 void DidInitializeOutputSurface() override { times_initialized_++; }
601
602 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override { EndTest(); }
603
604 void AfterTest() override {
605 EXPECT_EQ(times_to_fail_, times_create_failed_);
606 EXPECT_NE(0, times_initialized_);
607 }
608
609 private:
610 int times_to_fail_;
611 int times_initialized_;
612 };
613
614 SINGLE_AND_MULTI_THREAD_TEST_F(
615 LayerTreeHostContextTestCreateOutputSurfaceFailsOnce);
616
617 class LayerTreeHostContextTestLostContextAndEvictTextures
618 : public LayerTreeHostContextTest {
619 public:
620 LayerTreeHostContextTestLostContextAndEvictTextures()
621 : LayerTreeHostContextTest(),
622 impl_host_(0),
623 num_commits_(0),
624 lost_context_(false) {}
625
626 void SetupTree() override {
627 // Paint non-solid color.
628 SkPaint paint;
629 paint.setColor(SkColorSetARGB(100, 80, 200, 200));
630 client_.add_draw_rect(gfx::Rect(0, 0, 5, 5), paint);
631
632 if (layer_tree_host()->settings().impl_side_painting) {
633 picture_layer_ = FakePictureLayer::Create(&client_);
634 picture_layer_->SetBounds(gfx::Size(10, 20));
635 layer_tree_host()->SetRootLayer(picture_layer_);
636 } else {
637 content_layer_ = FakeContentLayer::Create(&client_);
638 content_layer_->SetBounds(gfx::Size(10, 20));
639 layer_tree_host()->SetRootLayer(content_layer_);
640 }
641
642 LayerTreeHostContextTest::SetupTree();
643 }
644
645 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
646
647 void PostEvictTextures() {
648 if (HasImplThread()) {
649 ImplThreadTaskRunner()->PostTask(
650 FROM_HERE,
651 base::Bind(&LayerTreeHostContextTestLostContextAndEvictTextures::
652 EvictTexturesOnImplThread,
653 base::Unretained(this)));
654 } else {
655 DebugScopedSetImplThread impl(proxy());
656 EvictTexturesOnImplThread();
657 }
658 }
659
660 void EvictTexturesOnImplThread() {
661 impl_host_->EvictTexturesForTesting();
662
663 if (lose_after_evict_) {
664 LoseContext();
665 lost_context_ = true;
666 }
667 }
668
669 void DidCommitAndDrawFrame() override {
670 if (num_commits_ > 1)
671 return;
672 if (!layer_tree_host()->settings().impl_side_painting) {
673 EXPECT_TRUE(content_layer_->HaveBackingAt(0, 0));
674 }
675 PostEvictTextures();
676 }
677
678 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
679 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
680 if (num_commits_ > 1)
681 return;
682 ++num_commits_;
683 if (!lose_after_evict_) {
684 LoseContext();
685 lost_context_ = true;
686 }
687 }
688
689 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
690 if (impl->settings().impl_side_painting) {
691 FakePictureLayerImpl* picture_impl =
692 static_cast<FakePictureLayerImpl*>(impl->active_tree()->root_layer());
693 EXPECT_TRUE(picture_impl->HighResTiling()->TileAt(0, 0)->IsReadyToDraw());
694 } else {
695 FakeContentLayerImpl* content_impl =
696 static_cast<FakeContentLayerImpl*>(impl->active_tree()->root_layer());
697 EXPECT_TRUE(content_impl->HaveResourceForTileAt(0, 0));
698 }
699
700 impl_host_ = impl;
701 if (lost_context_)
702 EndTest();
703 }
704
705 void DidInitializeOutputSurface() override {}
706
707 void AfterTest() override {}
708
709 protected:
710 bool lose_after_evict_;
711 FakeContentLayerClient client_;
712 scoped_refptr<FakeContentLayer> content_layer_;
713 scoped_refptr<FakePictureLayer> picture_layer_;
714 LayerTreeHostImpl* impl_host_;
715 int num_commits_;
716 bool lost_context_;
717 };
718
719 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
720 LoseAfterEvict_SingleThread_DirectRenderer) {
721 lose_after_evict_ = true;
722 RunTest(false, false, false);
723 }
724
725 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
726 LoseAfterEvict_SingleThread_DelegatingRenderer) {
727 lose_after_evict_ = true;
728 RunTest(false, true, false);
729 }
730
731 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
732 LoseAfterEvict_MultiThread_DirectRenderer_MainThreadPaint) {
733 lose_after_evict_ = true;
734 RunTest(true, false, false);
735 }
736
737 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
738 LoseAfterEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
739 lose_after_evict_ = true;
740 RunTest(true, true, false);
741 }
742
743 // Flaky on all platforms, http://crbug.com/310979
744 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
745 DISABLED_LoseAfterEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
746 lose_after_evict_ = true;
747 RunTest(true, true, true);
748 }
749
750 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
751 LoseBeforeEvict_SingleThread_DirectRenderer) {
752 lose_after_evict_ = false;
753 RunTest(false, false, false);
754 }
755
756 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
757 LoseBeforeEvict_SingleThread_DelegatingRenderer) {
758 lose_after_evict_ = false;
759 RunTest(false, true, false);
760 }
761
762 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
763 LoseBeforeEvict_MultiThread_DirectRenderer_MainThreadPaint) {
764 lose_after_evict_ = false;
765 RunTest(true, false, false);
766 }
767
768 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
769 LoseBeforeEvict_MultiThread_DirectRenderer_ImplSidePaint) {
770 lose_after_evict_ = false;
771 RunTest(true, false, true);
772 }
773
774 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
775 LoseBeforeEvict_MultiThread_DelegatingRenderer_MainThreadPaint) {
776 lose_after_evict_ = false;
777 RunTest(true, true, false);
778 }
779
780 TEST_F(LayerTreeHostContextTestLostContextAndEvictTextures,
781 LoseBeforeEvict_MultiThread_DelegatingRenderer_ImplSidePaint) {
782 lose_after_evict_ = false;
783 RunTest(true, true, true);
784 }
785
786 class LayerTreeHostContextTestLostContextWhileUpdatingResources
787 : public LayerTreeHostContextTest {
788 public:
789 LayerTreeHostContextTestLostContextWhileUpdatingResources()
790 : num_children_(50), times_to_lose_on_end_query_(3) {}
791
792 scoped_ptr<TestWebGraphicsContext3D> CreateContext3d() override {
793 scoped_ptr<TestWebGraphicsContext3D> context =
794 LayerTreeHostContextTest::CreateContext3d();
795 if (times_to_lose_on_end_query_) {
796 --times_to_lose_on_end_query_;
797 context->set_times_end_query_succeeds(5);
798 }
799 return context.Pass();
800 }
801
802 void SetupTree() override {
803 if (layer_tree_host()->settings().impl_side_painting)
804 parent_ = FakePictureLayer::Create(&client_);
805 else
806 parent_ = FakeContentLayer::Create(&client_);
807
808 parent_->SetBounds(gfx::Size(num_children_, 1));
809
810 for (int i = 0; i < num_children_; i++) {
811 scoped_refptr<Layer> child;
812 if (layer_tree_host()->settings().impl_side_painting)
813 child = FakePictureLayer::Create(&client_);
814 else
815 child = FakeContentLayer::Create(&client_);
816 child->SetPosition(gfx::PointF(i, 0.f));
817 child->SetBounds(gfx::Size(1, 1));
818 parent_->AddChild(child);
819 }
820
821 layer_tree_host()->SetRootLayer(parent_);
822 LayerTreeHostContextTest::SetupTree();
823 }
824
825 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
826
827 void DrawLayersOnThread(LayerTreeHostImpl* host_impl) override {
828 EXPECT_EQ(0, times_to_lose_on_end_query_);
829 EndTest();
830 }
831
832 void AfterTest() override { EXPECT_EQ(0, times_to_lose_on_end_query_); }
833
834 private:
835 FakeContentLayerClient client_;
836 scoped_refptr<Layer> parent_;
837 int num_children_;
838 int times_to_lose_on_end_query_;
839 };
840
841 SINGLE_AND_MULTI_THREAD_NOIMPL_TEST_F(
842 LayerTreeHostContextTestLostContextWhileUpdatingResources);
843
844 class LayerTreeHostContextTestLayersNotified : public LayerTreeHostContextTest {
845 public:
846 LayerTreeHostContextTestLayersNotified()
847 : LayerTreeHostContextTest(), num_commits_(0) {}
848
849 void SetupTree() override {
850 if (layer_tree_host()->settings().impl_side_painting) {
851 root_ = FakePictureLayer::Create(&client_);
852 child_ = FakePictureLayer::Create(&client_);
853 grandchild_ = FakePictureLayer::Create(&client_);
854 } else {
855 root_ = FakeContentLayer::Create(&client_);
856 child_ = FakeContentLayer::Create(&client_);
857 grandchild_ = FakeContentLayer::Create(&client_);
858 }
859
860 root_->AddChild(child_);
861 child_->AddChild(grandchild_);
862
863 layer_tree_host()->SetRootLayer(root_);
864 LayerTreeHostContextTest::SetupTree();
865 }
866
867 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
868
869 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
870 LayerTreeHostContextTest::DidActivateTreeOnThread(host_impl);
871
872 FakePictureLayerImpl* root_picture = NULL;
873 FakePictureLayerImpl* child_picture = NULL;
874 FakePictureLayerImpl* grandchild_picture = NULL;
875 FakeContentLayerImpl* root_content = NULL;
876 FakeContentLayerImpl* child_content = NULL;
877 FakeContentLayerImpl* grandchild_content = NULL;
878
879 if (host_impl->settings().impl_side_painting) {
880 root_picture = static_cast<FakePictureLayerImpl*>(
881 host_impl->active_tree()->root_layer());
882 child_picture =
883 static_cast<FakePictureLayerImpl*>(root_picture->children()[0]);
884 grandchild_picture =
885 static_cast<FakePictureLayerImpl*>(child_picture->children()[0]);
886
887 } else {
888 root_content = static_cast<FakeContentLayerImpl*>(
889 host_impl->active_tree()->root_layer());
890 child_content =
891 static_cast<FakeContentLayerImpl*>(root_content->children()[0]);
892 grandchild_content =
893 static_cast<FakeContentLayerImpl*>(child_content->children()[0]);
894 }
895
896 ++num_commits_;
897 switch (num_commits_) {
898 case 1:
899 if (host_impl->settings().impl_side_painting) {
900 EXPECT_EQ(0u, root_picture->release_resources_count());
901 EXPECT_EQ(0u, child_picture->release_resources_count());
902 EXPECT_EQ(0u, grandchild_picture->release_resources_count());
903 } else {
904 EXPECT_EQ(0u, root_content->lost_output_surface_count());
905 EXPECT_EQ(0u, child_content->lost_output_surface_count());
906 EXPECT_EQ(0u, grandchild_content->lost_output_surface_count());
907 }
908
909 // Lose the context and struggle to recreate it.
910 LoseContext();
911 times_to_fail_create_ = 1;
912 break;
913 case 2:
914 if (host_impl->settings().impl_side_painting) {
915 EXPECT_TRUE(root_picture->release_resources_count());
916 EXPECT_TRUE(child_picture->release_resources_count());
917 EXPECT_TRUE(grandchild_picture->release_resources_count());
918 } else {
919 EXPECT_TRUE(root_content->lost_output_surface_count());
920 EXPECT_TRUE(child_content->lost_output_surface_count());
921 EXPECT_TRUE(grandchild_content->lost_output_surface_count());
922 }
923
924 EndTest();
925 break;
926 default:
927 NOTREACHED();
928 }
929 }
930
931 void AfterTest() override {}
932
933 private:
934 int num_commits_;
935
936 FakeContentLayerClient client_;
937 scoped_refptr<Layer> root_;
938 scoped_refptr<Layer> child_;
939 scoped_refptr<Layer> grandchild_;
940 };
941
942 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestLayersNotified);
943
944 class LayerTreeHostContextTestDontUseLostResources
945 : public LayerTreeHostContextTest {
946 public:
947 LayerTreeHostContextTestDontUseLostResources() : lost_context_(false) {
948 context_should_support_io_surface_ = true;
949
950 child_output_surface_ = FakeOutputSurface::Create3d();
951 child_output_surface_->BindToClient(&output_surface_client_);
952 shared_bitmap_manager_.reset(new TestSharedBitmapManager());
953 child_resource_provider_ =
954 ResourceProvider::Create(child_output_surface_.get(),
955 shared_bitmap_manager_.get(),
956 NULL,
957 NULL,
958 0,
959 false,
960 1);
961 }
962
963 static void EmptyReleaseCallback(unsigned sync_point, bool lost) {}
964
965 void SetupTree() override {
966 gpu::gles2::GLES2Interface* gl =
967 child_output_surface_->context_provider()->ContextGL();
968
969 scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
970
971 scoped_ptr<TestRenderPass> pass_for_quad = TestRenderPass::Create();
972 pass_for_quad->SetNew(
973 // AppendOneOfEveryQuadType() makes a RenderPass quad with this id.
974 RenderPassId(2, 1),
975 gfx::Rect(0, 0, 10, 10),
976 gfx::Rect(0, 0, 10, 10),
977 gfx::Transform());
978
979 scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
980 pass->SetNew(RenderPassId(1, 1),
981 gfx::Rect(0, 0, 10, 10),
982 gfx::Rect(0, 0, 10, 10),
983 gfx::Transform());
984 pass->AppendOneOfEveryQuadType(child_resource_provider_.get(),
985 RenderPassId(2, 1));
986
987 frame_data->render_pass_list.push_back(pass_for_quad.Pass());
988 frame_data->render_pass_list.push_back(pass.Pass());
989
990 delegated_resource_collection_ = new DelegatedFrameResourceCollection;
991 delegated_frame_provider_ = new DelegatedFrameProvider(
992 delegated_resource_collection_.get(), frame_data.Pass());
993
994 ResourceProvider::ResourceId resource =
995 child_resource_provider_->CreateResource(
996 gfx::Size(4, 4), GL_CLAMP_TO_EDGE,
997 ResourceProvider::TEXTURE_HINT_IMMUTABLE, RGBA_8888);
998 ResourceProvider::ScopedWriteLockGL lock(child_resource_provider_.get(),
999 resource);
1000
1001 gpu::Mailbox mailbox;
1002 gl->GenMailboxCHROMIUM(mailbox.name);
1003 GLuint sync_point = gl->InsertSyncPointCHROMIUM();
1004
1005 scoped_refptr<Layer> root = Layer::Create();
1006 root->SetBounds(gfx::Size(10, 10));
1007 root->SetIsDrawable(true);
1008
1009 scoped_refptr<FakeDelegatedRendererLayer> delegated =
1010 FakeDelegatedRendererLayer::Create(delegated_frame_provider_.get());
1011 delegated->SetBounds(gfx::Size(10, 10));
1012 delegated->SetIsDrawable(true);
1013 root->AddChild(delegated);
1014
1015 scoped_refptr<Layer> layer;
1016 if (layer_tree_host()->settings().impl_side_painting)
1017 layer = PictureLayer::Create(&client_);
1018 else
1019 layer = ContentLayer::Create(&client_);
1020 layer->SetBounds(gfx::Size(10, 10));
1021 layer->SetIsDrawable(true);
1022 root->AddChild(layer);
1023
1024 scoped_refptr<TextureLayer> texture = TextureLayer::CreateForMailbox(NULL);
1025 texture->SetBounds(gfx::Size(10, 10));
1026 texture->SetIsDrawable(true);
1027 texture->SetTextureMailbox(
1028 TextureMailbox(mailbox, GL_TEXTURE_2D, sync_point),
1029 SingleReleaseCallback::Create(
1030 base::Bind(&LayerTreeHostContextTestDontUseLostResources::
1031 EmptyReleaseCallback)));
1032 root->AddChild(texture);
1033
1034 scoped_refptr<Layer> mask;
1035 if (layer_tree_host()->settings().impl_side_painting)
1036 mask = PictureLayer::Create(&client_);
1037 else
1038 mask = ContentLayer::Create(&client_);
1039 mask->SetBounds(gfx::Size(10, 10));
1040
1041 scoped_refptr<Layer> layer_with_mask;
1042 if (layer_tree_host()->settings().impl_side_painting)
1043 layer_with_mask = PictureLayer::Create(&client_);
1044 else
1045 layer_with_mask = ContentLayer::Create(&client_);
1046 layer_with_mask->SetBounds(gfx::Size(10, 10));
1047 layer_with_mask->SetIsDrawable(true);
1048 layer_with_mask->SetMaskLayer(mask.get());
1049 root->AddChild(layer_with_mask);
1050
1051 if (!delegating_renderer()) {
1052 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
1053 scoped_refptr<IOSurfaceLayer> io_surface = IOSurfaceLayer::Create();
1054 io_surface->SetBounds(gfx::Size(10, 10));
1055 io_surface->SetIsDrawable(true);
1056 io_surface->SetIOSurfaceProperties(1, gfx::Size(10, 10));
1057 root->AddChild(io_surface);
1058 }
1059
1060 // Enable the hud.
1061 LayerTreeDebugState debug_state;
1062 debug_state.show_property_changed_rects = true;
1063 layer_tree_host()->SetDebugState(debug_state);
1064
1065 scoped_refptr<PaintedScrollbarLayer> scrollbar =
1066 PaintedScrollbarLayer::Create(
1067 scoped_ptr<Scrollbar>(new FakeScrollbar).Pass(), layer->id());
1068 scrollbar->SetBounds(gfx::Size(10, 10));
1069 scrollbar->SetIsDrawable(true);
1070 root->AddChild(scrollbar);
1071
1072 layer_tree_host()->SetRootLayer(root);
1073 LayerTreeHostContextTest::SetupTree();
1074 }
1075
1076 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1077
1078 void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
1079 LayerTreeHostContextTest::CommitCompleteOnThread(host_impl);
1080 }
1081
1082 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
1083 LayerTreeHostImpl::FrameData* frame,
1084 DrawResult draw_result) override {
1085 if (host_impl->active_tree()->source_frame_number() == 2) {
1086 // Lose the context during draw on the second commit. This will cause
1087 // a third commit to recover.
1088 context3d_->set_times_bind_texture_succeeds(0);
1089 }
1090 return draw_result;
1091 }
1092
1093 scoped_ptr<FakeOutputSurface> CreateFakeOutputSurface() override {
1094 // This will get called twice:
1095 // First when we create the initial output surface...
1096 if (layer_tree_host()->source_frame_number() > 0) {
1097 // ... and then again after we forced the context to be lost.
1098 lost_context_ = true;
1099 }
1100 return LayerTreeHostContextTest::CreateFakeOutputSurface();
1101 }
1102
1103 void DidCommitAndDrawFrame() override {
1104 ASSERT_TRUE(layer_tree_host()->hud_layer());
1105 // End the test once we know the 3nd frame drew.
1106 if (layer_tree_host()->source_frame_number() < 5) {
1107 layer_tree_host()->root_layer()->SetNeedsDisplay();
1108 layer_tree_host()->SetNeedsCommit();
1109 } else {
1110 EndTest();
1111 }
1112 }
1113
1114 void AfterTest() override { EXPECT_TRUE(lost_context_); }
1115
1116 private:
1117 FakeContentLayerClient client_;
1118 bool lost_context_;
1119
1120 FakeOutputSurfaceClient output_surface_client_;
1121 scoped_ptr<FakeOutputSurface> child_output_surface_;
1122 scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
1123 scoped_ptr<ResourceProvider> child_resource_provider_;
1124
1125 scoped_refptr<DelegatedFrameResourceCollection>
1126 delegated_resource_collection_;
1127 scoped_refptr<DelegatedFrameProvider> delegated_frame_provider_;
1128 };
1129
1130 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestDontUseLostResources);
1131
1132 class ImplSidePaintingLayerTreeHostContextTest
1133 : public LayerTreeHostContextTest {
1134 public:
1135 void InitializeSettings(LayerTreeSettings* settings) override {
1136 settings->impl_side_painting = true;
1137 }
1138 };
1139
1140 class LayerTreeHostContextTestImplSidePainting
1141 : public ImplSidePaintingLayerTreeHostContextTest {
1142 public:
1143 void SetupTree() override {
1144 scoped_refptr<Layer> root = Layer::Create();
1145 root->SetBounds(gfx::Size(10, 10));
1146 root->SetIsDrawable(true);
1147
1148 scoped_refptr<PictureLayer> picture = PictureLayer::Create(&client_);
1149 picture->SetBounds(gfx::Size(10, 10));
1150 picture->SetIsDrawable(true);
1151 root->AddChild(picture);
1152
1153 layer_tree_host()->SetRootLayer(root);
1154 LayerTreeHostContextTest::SetupTree();
1155 }
1156
1157 void BeginTest() override {
1158 times_to_lose_during_commit_ = 1;
1159 PostSetNeedsCommitToMainThread();
1160 }
1161
1162 void AfterTest() override {}
1163
1164 void DidInitializeOutputSurface() override { EndTest(); }
1165
1166 private:
1167 FakeContentLayerClient client_;
1168 };
1169
1170 MULTI_THREAD_TEST_F(LayerTreeHostContextTestImplSidePainting);
1171
1172 class ScrollbarLayerLostContext : public LayerTreeHostContextTest {
1173 public:
1174 ScrollbarLayerLostContext() : commits_(0) {}
1175
1176 void BeginTest() override {
1177 scoped_refptr<Layer> scroll_layer = Layer::Create();
1178 scrollbar_layer_ =
1179 FakePaintedScrollbarLayer::Create(false, true, scroll_layer->id());
1180 scrollbar_layer_->SetBounds(gfx::Size(10, 100));
1181 layer_tree_host()->root_layer()->AddChild(scrollbar_layer_);
1182 layer_tree_host()->root_layer()->AddChild(scroll_layer);
1183 PostSetNeedsCommitToMainThread();
1184 }
1185
1186 void AfterTest() override {}
1187
1188 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
1189 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1190
1191 ++commits_;
1192 switch (commits_) {
1193 case 1:
1194 // First (regular) update, we should upload 2 resources (thumb, and
1195 // backtrack).
1196 EXPECT_EQ(1, scrollbar_layer_->update_count());
1197 LoseContext();
1198 break;
1199 case 2:
1200 // Second update, after the lost context, we should still upload 2
1201 // resources even if the contents haven't changed.
1202 EXPECT_EQ(2, scrollbar_layer_->update_count());
1203 EndTest();
1204 break;
1205 default:
1206 NOTREACHED();
1207 }
1208 }
1209
1210 private:
1211 int commits_;
1212 scoped_refptr<FakePaintedScrollbarLayer> scrollbar_layer_;
1213 };
1214
1215 SINGLE_AND_MULTI_THREAD_TEST_F(ScrollbarLayerLostContext);
1216
1217 class UIResourceLostTest : public LayerTreeHostContextTest {
1218 public:
1219 UIResourceLostTest() : time_step_(0) {}
1220 void InitializeSettings(LayerTreeSettings* settings) override {
1221 settings->renderer_settings.texture_id_allocation_chunk_size = 1;
1222 }
1223 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1224 void AfterTest() override {}
1225
1226 // This is called on the main thread after each commit and
1227 // DidActivateTreeOnThread, with the value of time_step_ at the time
1228 // of the call to DidActivateTreeOnThread. Similar tests will do
1229 // work on the main thread in DidCommit but that is unsuitable because
1230 // the main thread work for these tests must happen after
1231 // DidActivateTreeOnThread, which happens after DidCommit with impl-side
1232 // painting.
1233 virtual void StepCompleteOnMainThread(int time_step) = 0;
1234
1235 // Called after DidActivateTreeOnThread. If this is done during the commit,
1236 // the call to StepCompleteOnMainThread will not occur until after
1237 // the commit completes, because the main thread is blocked.
1238 void PostStepCompleteToMainThread() {
1239 proxy()->MainThreadTaskRunner()->PostTask(
1240 FROM_HERE,
1241 base::Bind(&UIResourceLostTest::StepCompleteOnMainThreadInternal,
1242 base::Unretained(this),
1243 time_step_));
1244 }
1245
1246 void PostLoseContextToImplThread() {
1247 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1248 ImplThreadTaskRunner()->PostTask(
1249 FROM_HERE,
1250 base::Bind(&LayerTreeHostContextTest::LoseContext,
1251 base::Unretained(this)));
1252 }
1253
1254 protected:
1255 int time_step_;
1256 scoped_ptr<FakeScopedUIResource> ui_resource_;
1257
1258 private:
1259 void StepCompleteOnMainThreadInternal(int step) {
1260 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1261 StepCompleteOnMainThread(step);
1262 }
1263 };
1264
1265 class UIResourceLostTestSimple : public UIResourceLostTest {
1266 public:
1267 // This is called when the commit is complete and the new layer tree has been
1268 // activated.
1269 virtual void StepCompleteOnImplThread(LayerTreeHostImpl* impl) = 0;
1270
1271 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
1272 if (!impl->settings().impl_side_painting) {
1273 StepCompleteOnImplThread(impl);
1274 PostStepCompleteToMainThread();
1275 ++time_step_;
1276 }
1277 }
1278
1279 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
1280 if (impl->settings().impl_side_painting) {
1281 StepCompleteOnImplThread(impl);
1282 PostStepCompleteToMainThread();
1283 ++time_step_;
1284 }
1285 }
1286 };
1287
1288 // Losing context after an UI resource has been created.
1289 class UIResourceLostAfterCommit : public UIResourceLostTestSimple {
1290 public:
1291 void StepCompleteOnMainThread(int step) override {
1292 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1293 switch (step) {
1294 case 0:
1295 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1296 // Expects a valid UIResourceId.
1297 EXPECT_NE(0, ui_resource_->id());
1298 PostSetNeedsCommitToMainThread();
1299 break;
1300 case 4:
1301 // Release resource before ending the test.
1302 ui_resource_ = nullptr;
1303 EndTest();
1304 break;
1305 case 5:
1306 NOTREACHED();
1307 break;
1308 }
1309 }
1310
1311 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
1312 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1313 switch (time_step_) {
1314 case 1:
1315 // The resource should have been created on LTHI after the commit.
1316 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1317 PostSetNeedsCommitToMainThread();
1318 break;
1319 case 2:
1320 LoseContext();
1321 break;
1322 case 3:
1323 // The resources should have been recreated. The bitmap callback should
1324 // have been called once with the resource_lost flag set to true.
1325 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1326 // Resource Id on the impl-side have been recreated as well. Note
1327 // that the same UIResourceId persists after the context lost.
1328 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1329 PostSetNeedsCommitToMainThread();
1330 break;
1331 }
1332 }
1333 };
1334
1335 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostAfterCommit);
1336
1337 // Losing context before UI resource requests can be commited. Three sequences
1338 // of creation/deletion are considered:
1339 // 1. Create one resource -> Context Lost => Expect the resource to have been
1340 // created.
1341 // 2. Delete an exisiting resource (test_id0_) -> create a second resource
1342 // (test_id1_) -> Context Lost => Expect the test_id0_ to be removed and
1343 // test_id1_ to have been created.
1344 // 3. Create one resource -> Delete that same resource -> Context Lost => Expect
1345 // the resource to not exist in the manager.
1346 class UIResourceLostBeforeCommit : public UIResourceLostTestSimple {
1347 public:
1348 UIResourceLostBeforeCommit() : test_id0_(0), test_id1_(0) {}
1349
1350 void StepCompleteOnMainThread(int step) override {
1351 switch (step) {
1352 case 0:
1353 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1354 // Lose the context on the impl thread before the commit.
1355 PostLoseContextToImplThread();
1356 break;
1357 case 2:
1358 // Sequence 2:
1359 // Currently one resource has been created.
1360 test_id0_ = ui_resource_->id();
1361 // Delete this resource.
1362 ui_resource_ = nullptr;
1363 // Create another resource.
1364 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1365 test_id1_ = ui_resource_->id();
1366 // Sanity check that two resource creations return different ids.
1367 EXPECT_NE(test_id0_, test_id1_);
1368 // Lose the context on the impl thread before the commit.
1369 PostLoseContextToImplThread();
1370 break;
1371 case 3:
1372 // Clear the manager of resources.
1373 ui_resource_ = nullptr;
1374 PostSetNeedsCommitToMainThread();
1375 break;
1376 case 4:
1377 // Sequence 3:
1378 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1379 test_id0_ = ui_resource_->id();
1380 // Sanity check the UIResourceId should not be 0.
1381 EXPECT_NE(0, test_id0_);
1382 // Usually ScopedUIResource are deleted from the manager in their
1383 // destructor (so usually ui_resource_ = nullptr). But here we need
1384 // ui_resource_ for the next step, so call DeleteUIResource directly.
1385 layer_tree_host()->DeleteUIResource(test_id0_);
1386 // Delete the resouce and then lose the context.
1387 PostLoseContextToImplThread();
1388 break;
1389 case 5:
1390 // Release resource before ending the test.
1391 ui_resource_ = nullptr;
1392 EndTest();
1393 break;
1394 case 6:
1395 NOTREACHED();
1396 break;
1397 }
1398 }
1399
1400 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
1401 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1402 switch (time_step_) {
1403 case 1:
1404 // Sequence 1 (continued):
1405 // The first context lost happens before the resources were created,
1406 // and because it resulted in no resources being destroyed, it does not
1407 // trigger resource re-creation.
1408 EXPECT_EQ(1, ui_resource_->resource_create_count);
1409 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1410 // Resource Id on the impl-side has been created.
1411 PostSetNeedsCommitToMainThread();
1412 break;
1413 case 3:
1414 // Sequence 2 (continued):
1415 // The previous resource should have been deleted.
1416 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1417 // The second resource should have been created.
1418 EXPECT_NE(0u, impl->ResourceIdForUIResource(test_id1_));
1419 // The second resource called the resource callback once and since the
1420 // context is lost, a "resource lost" callback was also issued.
1421 EXPECT_EQ(2, ui_resource_->resource_create_count);
1422 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1423 break;
1424 case 5:
1425 // Sequence 3 (continued):
1426 // Expect the resource callback to have been called once.
1427 EXPECT_EQ(1, ui_resource_->resource_create_count);
1428 // No "resource lost" callbacks.
1429 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1430 // The UI resource id should not be valid
1431 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id0_));
1432 break;
1433 }
1434 }
1435
1436 private:
1437 UIResourceId test_id0_;
1438 UIResourceId test_id1_;
1439 };
1440
1441 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostBeforeCommit);
1442
1443 // Losing UI resource before the pending trees is activated but after the
1444 // commit. Impl-side-painting only.
1445 class UIResourceLostBeforeActivateTree : public UIResourceLostTest {
1446 void StepCompleteOnMainThread(int step) override {
1447 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1448 switch (step) {
1449 case 0:
1450 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1451 PostSetNeedsCommitToMainThread();
1452 break;
1453 case 3:
1454 test_id_ = ui_resource_->id();
1455 ui_resource_ = nullptr;
1456 PostSetNeedsCommitToMainThread();
1457 break;
1458 case 5:
1459 // Release resource before ending the test.
1460 ui_resource_ = nullptr;
1461 EndTest();
1462 break;
1463 case 6:
1464 // Make sure no extra commits happened.
1465 NOTREACHED();
1466 }
1467 }
1468
1469 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
1470 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1471 switch (time_step_) {
1472 case 2:
1473 PostSetNeedsCommitToMainThread();
1474 break;
1475 case 4:
1476 PostSetNeedsCommitToMainThread();
1477 break;
1478 }
1479 }
1480
1481 void WillActivateTreeOnThread(LayerTreeHostImpl* impl) override {
1482 switch (time_step_) {
1483 case 1:
1484 // The resource creation callback has been called.
1485 EXPECT_EQ(1, ui_resource_->resource_create_count);
1486 // The resource is not yet lost (sanity check).
1487 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1488 // The resource should not have been created yet on the impl-side.
1489 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1490 LoseContext();
1491 break;
1492 case 3:
1493 LoseContext();
1494 break;
1495 }
1496 }
1497
1498 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
1499 LayerTreeHostContextTest::DidActivateTreeOnThread(impl);
1500 switch (time_step_) {
1501 case 1:
1502 // The pending requests on the impl-side should have been processed.
1503 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1504 break;
1505 case 2:
1506 // The "lost resource" callback should have been called once.
1507 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1508 break;
1509 case 4:
1510 // The resource is deleted and should not be in the manager. Use
1511 // test_id_ since ui_resource_ has been deleted.
1512 EXPECT_EQ(0u, impl->ResourceIdForUIResource(test_id_));
1513 break;
1514 }
1515
1516 PostStepCompleteToMainThread();
1517 ++time_step_;
1518 }
1519
1520 private:
1521 UIResourceId test_id_;
1522 };
1523
1524 TEST_F(UIResourceLostBeforeActivateTree,
1525 RunMultiThread_DirectRenderer_ImplSidePaint) {
1526 RunTest(true, false, true);
1527 }
1528
1529 TEST_F(UIResourceLostBeforeActivateTree,
1530 RunMultiThread_DelegatingRenderer_ImplSidePaint) {
1531 RunTest(true, true, true);
1532 }
1533
1534 // Resources evicted explicitly and by visibility changes.
1535 class UIResourceLostEviction : public UIResourceLostTestSimple {
1536 public:
1537 void StepCompleteOnMainThread(int step) override {
1538 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
1539 switch (step) {
1540 case 0:
1541 ui_resource_ = FakeScopedUIResource::Create(layer_tree_host());
1542 EXPECT_NE(0, ui_resource_->id());
1543 PostSetNeedsCommitToMainThread();
1544 break;
1545 case 2:
1546 // Make the tree not visible.
1547 PostSetVisibleToMainThread(false);
1548 break;
1549 case 3:
1550 // Release resource before ending the test.
1551 ui_resource_ = nullptr;
1552 EndTest();
1553 break;
1554 case 4:
1555 NOTREACHED();
1556 }
1557 }
1558
1559 void DidSetVisibleOnImplTree(LayerTreeHostImpl* impl, bool visible) override {
1560 TestWebGraphicsContext3D* context = TestContext();
1561 if (!visible) {
1562 // All resources should have been evicted.
1563 ASSERT_EQ(0u, context->NumTextures());
1564 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1565 EXPECT_EQ(2, ui_resource_->resource_create_count);
1566 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1567 // Drawing is disabled both because of the evicted resources and
1568 // because the renderer is not visible.
1569 EXPECT_FALSE(impl->CanDraw());
1570 // Make the renderer visible again.
1571 PostSetVisibleToMainThread(true);
1572 }
1573 }
1574
1575 void StepCompleteOnImplThread(LayerTreeHostImpl* impl) override {
1576 TestWebGraphicsContext3D* context = TestContext();
1577 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1578 switch (time_step_) {
1579 case 1:
1580 // The resource should have been created on LTHI after the commit.
1581 ASSERT_EQ(1u, context->NumTextures());
1582 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1583 EXPECT_EQ(1, ui_resource_->resource_create_count);
1584 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1585 EXPECT_TRUE(impl->CanDraw());
1586 // Evict all UI resources. This will trigger a commit.
1587 impl->EvictAllUIResources();
1588 ASSERT_EQ(0u, context->NumTextures());
1589 EXPECT_EQ(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1590 EXPECT_EQ(1, ui_resource_->resource_create_count);
1591 EXPECT_EQ(0, ui_resource_->lost_resource_count);
1592 EXPECT_FALSE(impl->CanDraw());
1593 break;
1594 case 2:
1595 // The resource should have been recreated.
1596 ASSERT_EQ(1u, context->NumTextures());
1597 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1598 EXPECT_EQ(2, ui_resource_->resource_create_count);
1599 EXPECT_EQ(1, ui_resource_->lost_resource_count);
1600 EXPECT_TRUE(impl->CanDraw());
1601 break;
1602 case 3:
1603 // The resource should have been recreated after visibility was
1604 // restored.
1605 ASSERT_EQ(1u, context->NumTextures());
1606 EXPECT_NE(0u, impl->ResourceIdForUIResource(ui_resource_->id()));
1607 EXPECT_EQ(3, ui_resource_->resource_create_count);
1608 EXPECT_EQ(2, ui_resource_->lost_resource_count);
1609 EXPECT_TRUE(impl->CanDraw());
1610 break;
1611 }
1612 }
1613 };
1614
1615 SINGLE_AND_MULTI_THREAD_TEST_F(UIResourceLostEviction);
1616
1617 class LayerTreeHostContextTestSurfaceCreateCallback
1618 : public LayerTreeHostContextTest {
1619 public:
1620 LayerTreeHostContextTestSurfaceCreateCallback()
1621 : LayerTreeHostContextTest() {}
1622
1623 void SetupTree() override {
1624 if (layer_tree_host()->settings().impl_side_painting) {
1625 picture_layer_ = FakePictureLayer::Create(&client_);
1626 picture_layer_->SetBounds(gfx::Size(10, 20));
1627 layer_tree_host()->SetRootLayer(picture_layer_);
1628 } else {
1629 content_layer_ = FakeContentLayer::Create(&client_);
1630 content_layer_->SetBounds(gfx::Size(10, 20));
1631 layer_tree_host()->SetRootLayer(content_layer_);
1632 }
1633
1634 LayerTreeHostContextTest::SetupTree();
1635 }
1636
1637 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1638
1639 void DidCommit() override {
1640 switch (layer_tree_host()->source_frame_number()) {
1641 case 1:
1642 if (layer_tree_host()->settings().impl_side_painting)
1643 EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
1644 else
1645 EXPECT_EQ(1u, content_layer_->output_surface_created_count());
1646 layer_tree_host()->SetNeedsCommit();
1647 break;
1648 case 2:
1649 if (layer_tree_host()->settings().impl_side_painting)
1650 EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
1651 else
1652 EXPECT_EQ(1u, content_layer_->output_surface_created_count());
1653 layer_tree_host()->SetNeedsCommit();
1654 break;
1655 case 3:
1656 if (layer_tree_host()->settings().impl_side_painting)
1657 EXPECT_EQ(1u, picture_layer_->output_surface_created_count());
1658 else
1659 EXPECT_EQ(1u, content_layer_->output_surface_created_count());
1660 break;
1661 case 4:
1662 if (layer_tree_host()->settings().impl_side_painting)
1663 EXPECT_EQ(2u, picture_layer_->output_surface_created_count());
1664 else
1665 EXPECT_EQ(2u, content_layer_->output_surface_created_count());
1666 layer_tree_host()->SetNeedsCommit();
1667 break;
1668 }
1669 }
1670
1671 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
1672 LayerTreeHostContextTest::CommitCompleteOnThread(impl);
1673 switch (LastCommittedSourceFrameNumber(impl)) {
1674 case 0:
1675 break;
1676 case 1:
1677 break;
1678 case 2:
1679 LoseContext();
1680 break;
1681 case 3:
1682 EndTest();
1683 break;
1684 }
1685 }
1686
1687 void AfterTest() override {}
1688
1689 protected:
1690 FakeContentLayerClient client_;
1691 scoped_refptr<FakePictureLayer> picture_layer_;
1692 scoped_refptr<FakeContentLayer> content_layer_;
1693 };
1694
1695 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostContextTestSurfaceCreateCallback);
1696
1697 class LayerTreeHostContextTestLoseAfterSendingBeginMainFrame
1698 : public LayerTreeHostContextTest {
1699 protected:
1700 void BeginTest() override {
1701 deferred_ = false;
1702 PostSetNeedsCommitToMainThread();
1703 }
1704
1705 void ScheduledActionWillSendBeginMainFrame() override {
1706 if (deferred_)
1707 return;
1708 deferred_ = true;
1709
1710 // Defer commits before the BeginFrame arrives, causing it to be delayed.
1711 PostSetDeferCommitsToMainThread(true);
1712 // Meanwhile, lose the context while we are in defer commits.
1713 ImplThreadTaskRunner()->PostTask(
1714 FROM_HERE,
1715 base::Bind(&LayerTreeHostContextTestLoseAfterSendingBeginMainFrame::
1716 LoseContextOnImplThread,
1717 base::Unretained(this)));
1718 }
1719
1720 void LoseContextOnImplThread() {
1721 LoseContext();
1722
1723 // After losing the context, stop deferring commits.
1724 PostSetDeferCommitsToMainThread(false);
1725 }
1726
1727 void WillBeginMainFrame() override {
1728 // Don't begin a frame with a lost surface.
1729 EXPECT_FALSE(layer_tree_host()->output_surface_lost());
1730 }
1731
1732 void DidCommitAndDrawFrame() override { EndTest(); }
1733
1734 void AfterTest() override {}
1735
1736 bool deferred_;
1737 };
1738
1739 SINGLE_AND_MULTI_THREAD_TEST_F(
1740 LayerTreeHostContextTestLoseAfterSendingBeginMainFrame);
1741
1742 } // namespace
1743 } // namespace cc
OLDNEW
« no previous file with comments | « cc/trees/layer_tree_host_unittest_animation.cc ('k') | cc/trees/layer_tree_host_unittest_copyrequest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698