Revert 207508 "Add a hide_layer_and_subtree() flag to cc::Layer"
[chromium-blink-merge.git] / cc / trees / layer_tree_host_unittest.cc
blobed6dd2c9fc5f250c3bc9b3fe0d5c2c579800c5d0
1 // Copyright 2011 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 <algorithm>
9 #include "base/synchronization/lock.h"
10 #include "cc/animation/timing_function.h"
11 #include "cc/debug/frame_rate_counter.h"
12 #include "cc/layers/content_layer.h"
13 #include "cc/layers/content_layer_client.h"
14 #include "cc/layers/io_surface_layer.h"
15 #include "cc/layers/layer_impl.h"
16 #include "cc/layers/picture_layer.h"
17 #include "cc/layers/scrollbar_layer.h"
18 #include "cc/output/begin_frame_args.h"
19 #include "cc/output/copy_output_request.h"
20 #include "cc/output/copy_output_result.h"
21 #include "cc/output/output_surface.h"
22 #include "cc/resources/prioritized_resource.h"
23 #include "cc/resources/prioritized_resource_manager.h"
24 #include "cc/resources/resource_update_queue.h"
25 #include "cc/scheduler/frame_rate_controller.h"
26 #include "cc/test/fake_content_layer.h"
27 #include "cc/test/fake_content_layer_client.h"
28 #include "cc/test/fake_layer_tree_host_client.h"
29 #include "cc/test/fake_output_surface.h"
30 #include "cc/test/fake_picture_layer.h"
31 #include "cc/test/fake_picture_layer_impl.h"
32 #include "cc/test/fake_proxy.h"
33 #include "cc/test/fake_scrollbar_layer.h"
34 #include "cc/test/geometry_test_utils.h"
35 #include "cc/test/layer_tree_test.h"
36 #include "cc/test/occlusion_tracker_test_common.h"
37 #include "cc/trees/layer_tree_host_impl.h"
38 #include "cc/trees/layer_tree_impl.h"
39 #include "cc/trees/single_thread_proxy.h"
40 #include "cc/trees/thread_proxy.h"
41 #include "gpu/GLES2/gl2extchromium.h"
42 #include "skia/ext/refptr.h"
43 #include "testing/gmock/include/gmock/gmock.h"
44 #include "third_party/khronos/GLES2/gl2.h"
45 #include "third_party/khronos/GLES2/gl2ext.h"
46 #include "third_party/skia/include/core/SkPicture.h"
47 #include "ui/gfx/point_conversions.h"
48 #include "ui/gfx/size_conversions.h"
49 #include "ui/gfx/vector2d_conversions.h"
51 using testing::_;
52 using testing::AnyNumber;
53 using testing::AtLeast;
54 using testing::Mock;
56 namespace cc {
57 namespace {
59 class LayerTreeHostTest : public LayerTreeTest {
62 // Test interleaving of redraws and commits
63 class LayerTreeHostTestCommitingWithContinuousRedraw
64 : public LayerTreeHostTest {
65 public:
66 LayerTreeHostTestCommitingWithContinuousRedraw()
67 : num_complete_commits_(0), num_draws_(0) {}
69 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
71 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
72 num_complete_commits_++;
73 if (num_complete_commits_ == 2)
74 EndTest();
77 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
78 if (num_draws_ == 1)
79 PostSetNeedsCommitToMainThread();
80 num_draws_++;
81 PostSetNeedsRedrawToMainThread();
84 virtual void AfterTest() OVERRIDE {}
86 private:
87 int num_complete_commits_;
88 int num_draws_;
91 MULTI_THREAD_TEST_F(LayerTreeHostTestCommitingWithContinuousRedraw);
93 // Two setNeedsCommits in a row should lead to at least 1 commit and at least 1
94 // draw with frame 0.
95 class LayerTreeHostTestSetNeedsCommit1 : public LayerTreeHostTest {
96 public:
97 LayerTreeHostTestSetNeedsCommit1() : num_commits_(0), num_draws_(0) {}
99 virtual void BeginTest() OVERRIDE {
100 PostSetNeedsCommitToMainThread();
101 PostSetNeedsCommitToMainThread();
104 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
105 num_draws_++;
106 if (!impl->active_tree()->source_frame_number())
107 EndTest();
110 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
111 num_commits_++;
114 virtual void AfterTest() OVERRIDE {
115 EXPECT_GE(1, num_commits_);
116 EXPECT_GE(1, num_draws_);
119 private:
120 int num_commits_;
121 int num_draws_;
124 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsCommit1);
126 // A SetNeedsCommit should lead to 1 commit. Issuing a second commit after that
127 // first committed frame draws should lead to another commit.
128 class LayerTreeHostTestSetNeedsCommit2 : public LayerTreeHostTest {
129 public:
130 LayerTreeHostTestSetNeedsCommit2() : num_commits_(0), num_draws_(0) {}
132 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
134 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
135 ++num_draws_;
138 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
139 ++num_commits_;
140 switch (num_commits_) {
141 case 1:
142 PostSetNeedsCommitToMainThread();
143 break;
144 case 2:
145 EndTest();
146 break;
147 default:
148 NOTREACHED();
152 virtual void AfterTest() OVERRIDE {
153 EXPECT_EQ(2, num_commits_);
154 EXPECT_LE(1, num_draws_);
157 private:
158 int num_commits_;
159 int num_draws_;
162 MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsCommit2);
164 // 1 setNeedsRedraw after the first commit has completed should lead to 1
165 // additional draw.
166 class LayerTreeHostTestSetNeedsRedraw : public LayerTreeHostTest {
167 public:
168 LayerTreeHostTestSetNeedsRedraw() : num_commits_(0), num_draws_(0) {}
170 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
172 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
173 EXPECT_EQ(0, impl->active_tree()->source_frame_number());
174 if (!num_draws_) {
175 // Redraw again to verify that the second redraw doesn't commit.
176 PostSetNeedsRedrawToMainThread();
177 } else {
178 EndTest();
180 num_draws_++;
183 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
184 EXPECT_EQ(0, num_draws_);
185 num_commits_++;
188 virtual void AfterTest() OVERRIDE {
189 EXPECT_GE(2, num_draws_);
190 EXPECT_EQ(1, num_commits_);
193 private:
194 int num_commits_;
195 int num_draws_;
198 MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsRedraw);
200 // After setNeedsRedrawRect(invalid_rect) the final damage_rect
201 // must contain invalid_rect.
202 class LayerTreeHostTestSetNeedsRedrawRect : public LayerTreeHostTest {
203 public:
204 LayerTreeHostTestSetNeedsRedrawRect()
205 : num_draws_(0),
206 bounds_(50, 50),
207 invalid_rect_(10, 10, 20, 20),
208 root_layer_(ContentLayer::Create(&client_)) {
211 virtual void BeginTest() OVERRIDE {
212 root_layer_->SetIsDrawable(true);
213 root_layer_->SetBounds(bounds_);
214 layer_tree_host()->SetRootLayer(root_layer_);
215 layer_tree_host()->SetViewportSize(bounds_);
216 PostSetNeedsCommitToMainThread();
219 virtual bool PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
220 LayerTreeHostImpl::FrameData* frame_data,
221 bool result) OVERRIDE {
222 EXPECT_TRUE(result);
224 gfx::RectF root_damage_rect;
225 if (!frame_data->render_passes.empty())
226 root_damage_rect = frame_data->render_passes.back()->damage_rect;
228 if (!num_draws_) {
229 // If this is the first frame, expect full frame damage.
230 EXPECT_RECT_EQ(root_damage_rect, gfx::Rect(bounds_));
231 } else {
232 // Check that invalid_rect_ is indeed repainted.
233 EXPECT_TRUE(root_damage_rect.Contains(invalid_rect_));
236 return result;
239 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
240 if (!num_draws_) {
241 PostSetNeedsRedrawRectToMainThread(invalid_rect_);
242 } else {
243 EndTest();
245 num_draws_++;
248 virtual void AfterTest() OVERRIDE {
249 EXPECT_EQ(2, num_draws_);
252 private:
253 int num_draws_;
254 const gfx::Size bounds_;
255 const gfx::Rect invalid_rect_;
256 FakeContentLayerClient client_;
257 scoped_refptr<ContentLayer> root_layer_;
260 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSetNeedsRedrawRect);
262 class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest {
263 public:
264 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
265 settings->layer_transforms_should_scale_layer_contents = true;
268 virtual void SetupTree() OVERRIDE {
269 root_layer_ = Layer::Create();
270 root_layer_->SetBounds(gfx::Size(10, 20));
272 scaled_layer_ = FakeContentLayer::Create(&client_);
273 scaled_layer_->SetBounds(gfx::Size(1, 1));
274 root_layer_->AddChild(scaled_layer_);
276 layer_tree_host()->SetRootLayer(root_layer_);
277 LayerTreeHostTest::SetupTree();
280 virtual void BeginTest() OVERRIDE {
281 PostSetNeedsCommitToMainThread();
284 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
285 if (host_impl->active_tree()->source_frame_number() == 1)
286 EndTest();
289 virtual void DidCommit() OVERRIDE {
290 switch (layer_tree_host()->commit_number()) {
291 case 1:
292 // Changing the device scale factor causes a commit. It also changes
293 // the content bounds of |scaled_layer_|, which should not generate
294 // a second commit as a result.
295 layer_tree_host()->SetDeviceScaleFactor(4.f);
296 break;
297 default:
298 // No extra commits.
299 EXPECT_EQ(2, layer_tree_host()->commit_number());
303 virtual void AfterTest() OVERRIDE {
304 EXPECT_EQ(gfx::Size(4, 4).ToString(),
305 scaled_layer_->content_bounds().ToString());
308 private:
309 FakeContentLayerClient client_;
310 scoped_refptr<Layer> root_layer_;
311 scoped_refptr<FakeContentLayer> scaled_layer_;
314 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestNoExtraCommitFromInvalidate);
316 class LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate
317 : public LayerTreeHostTest {
318 public:
319 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
320 settings->layer_transforms_should_scale_layer_contents = true;
323 virtual void SetupTree() OVERRIDE {
324 root_layer_ = Layer::Create();
325 root_layer_->SetBounds(gfx::Size(10, 20));
327 bool paint_scrollbar = true;
328 bool has_thumb = false;
329 scrollbar_ = FakeScrollbarLayer::Create(paint_scrollbar,
330 has_thumb,
331 root_layer_->id());
332 scrollbar_->SetPosition(gfx::Point(0, 10));
333 scrollbar_->SetBounds(gfx::Size(10, 10));
335 root_layer_->AddChild(scrollbar_);
337 layer_tree_host()->SetRootLayer(root_layer_);
338 LayerTreeHostTest::SetupTree();
341 virtual void BeginTest() OVERRIDE {
342 PostSetNeedsCommitToMainThread();
345 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
346 if (host_impl->active_tree()->source_frame_number() == 1)
347 EndTest();
350 virtual void DidCommit() OVERRIDE {
351 switch (layer_tree_host()->commit_number()) {
352 case 1:
353 // Changing the device scale factor causes a commit. It also changes
354 // the content bounds of |scrollbar_|, which should not generate
355 // a second commit as a result.
356 layer_tree_host()->SetDeviceScaleFactor(4.f);
357 break;
358 default:
359 // No extra commits.
360 EXPECT_EQ(2, layer_tree_host()->commit_number());
364 virtual void AfterTest() OVERRIDE {
365 EXPECT_EQ(gfx::Size(40, 40).ToString(),
366 scrollbar_->content_bounds().ToString());
369 private:
370 FakeContentLayerClient client_;
371 scoped_refptr<Layer> root_layer_;
372 scoped_refptr<FakeScrollbarLayer> scrollbar_;
375 SINGLE_AND_MULTI_THREAD_TEST_F(
376 LayerTreeHostTestNoExtraCommitFromScrollbarInvalidate);
378 class LayerTreeHostTestCompositeAndReadback : public LayerTreeHostTest {
379 public:
380 LayerTreeHostTestCompositeAndReadback() : num_commits_(0) {}
382 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
384 virtual void DidCommit() OVERRIDE {
385 num_commits_++;
386 if (num_commits_ == 1) {
387 char pixels[4];
388 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
389 } else if (num_commits_ == 2) {
390 // This is inside the readback. We should get another commit after it.
391 } else if (num_commits_ == 3) {
392 EndTest();
393 } else {
394 NOTREACHED();
398 virtual void AfterTest() OVERRIDE {}
400 private:
401 int num_commits_;
404 MULTI_THREAD_TEST_F(LayerTreeHostTestCompositeAndReadback);
406 class LayerTreeHostTestCompositeAndReadbackBeforePreviousCommitDraws
407 : public LayerTreeHostTest {
408 public:
409 LayerTreeHostTestCompositeAndReadbackBeforePreviousCommitDraws()
410 : num_commits_(0) {}
412 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
414 virtual void DidCommit() OVERRIDE {
415 num_commits_++;
416 if (num_commits_ == 1) {
417 layer_tree_host()->SetNeedsCommit();
418 } else if (num_commits_ == 2) {
419 char pixels[4];
420 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
421 } else if (num_commits_ == 3) {
422 // This is inside the readback. We should get another commit after it.
423 } else if (num_commits_ == 4) {
424 EndTest();
425 } else {
426 NOTREACHED();
430 virtual void AfterTest() OVERRIDE {}
432 private:
433 int num_commits_;
436 MULTI_THREAD_TEST_F(
437 LayerTreeHostTestCompositeAndReadbackBeforePreviousCommitDraws);
439 // If the layerTreeHost says it can't draw, Then we should not try to draw.
440 class LayerTreeHostTestCanDrawBlocksDrawing : public LayerTreeHostTest {
441 public:
442 LayerTreeHostTestCanDrawBlocksDrawing() : num_commits_(0), done_(false) {}
444 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
446 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
447 if (done_)
448 return;
449 // Only the initial draw should bring us here.
450 EXPECT_TRUE(impl->CanDraw());
451 EXPECT_EQ(0, impl->active_tree()->source_frame_number());
454 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
455 if (done_)
456 return;
457 if (num_commits_ >= 1) {
458 // After the first commit, we should not be able to draw.
459 EXPECT_FALSE(impl->CanDraw());
463 virtual void DidCommit() OVERRIDE {
464 num_commits_++;
465 if (num_commits_ == 1) {
466 // Make the viewport empty so the host says it can't draw.
467 layer_tree_host()->SetViewportSize(gfx::Size(0, 0));
468 } else if (num_commits_ == 2) {
469 char pixels[4];
470 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
471 } else if (num_commits_ == 3) {
472 // Let it draw so we go idle and end the test.
473 layer_tree_host()->SetViewportSize(gfx::Size(1, 1));
474 done_ = true;
475 EndTest();
479 virtual void AfterTest() OVERRIDE {}
481 private:
482 int num_commits_;
483 bool done_;
486 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestCanDrawBlocksDrawing);
488 // beginLayerWrite should prevent draws from executing until a commit occurs
489 class LayerTreeHostTestWriteLayersRedraw : public LayerTreeHostTest {
490 public:
491 LayerTreeHostTestWriteLayersRedraw() : num_commits_(0), num_draws_(0) {}
493 virtual void BeginTest() OVERRIDE {
494 PostAcquireLayerTextures();
495 PostSetNeedsRedrawToMainThread(); // should be inhibited without blocking
496 PostSetNeedsCommitToMainThread();
499 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
500 num_draws_++;
501 EXPECT_EQ(num_draws_, num_commits_);
504 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
505 num_commits_++;
506 EndTest();
509 virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, num_commits_); }
511 private:
512 int num_commits_;
513 int num_draws_;
516 MULTI_THREAD_TEST_F(LayerTreeHostTestWriteLayersRedraw);
518 // Verify that when resuming visibility, Requesting layer write permission
519 // will not deadlock the main thread even though there are not yet any
520 // scheduled redraws. This behavior is critical for reliably surviving tab
521 // switching. There are no failure conditions to this test, it just passes
522 // by not timing out.
523 class LayerTreeHostTestWriteLayersAfterVisible : public LayerTreeHostTest {
524 public:
525 LayerTreeHostTestWriteLayersAfterVisible() : num_commits_(0) {}
527 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
529 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
530 num_commits_++;
531 if (num_commits_ == 2)
532 EndTest();
533 else if (num_commits_ < 2) {
534 PostSetVisibleToMainThread(false);
535 PostSetVisibleToMainThread(true);
536 PostAcquireLayerTextures();
537 PostSetNeedsCommitToMainThread();
541 virtual void AfterTest() OVERRIDE {}
543 private:
544 int num_commits_;
547 MULTI_THREAD_TEST_F(LayerTreeHostTestWriteLayersAfterVisible);
549 // A compositeAndReadback while invisible should force a normal commit without
550 // assertion.
551 class LayerTreeHostTestCompositeAndReadbackWhileInvisible
552 : public LayerTreeHostTest {
553 public:
554 LayerTreeHostTestCompositeAndReadbackWhileInvisible() : num_commits_(0) {}
556 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
558 virtual void DidCommitAndDrawFrame() OVERRIDE {
559 num_commits_++;
560 if (num_commits_ == 1) {
561 layer_tree_host()->SetVisible(false);
562 layer_tree_host()->SetNeedsCommit();
563 layer_tree_host()->SetNeedsCommit();
564 char pixels[4];
565 layer_tree_host()->CompositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
566 } else {
567 EndTest();
571 virtual void AfterTest() OVERRIDE {}
573 private:
574 int num_commits_;
577 MULTI_THREAD_TEST_F(LayerTreeHostTestCompositeAndReadbackWhileInvisible);
579 class LayerTreeHostTestAbortFrameWhenInvisible : public LayerTreeHostTest {
580 public:
581 LayerTreeHostTestAbortFrameWhenInvisible() {}
583 virtual void BeginTest() OVERRIDE {
584 // Request a commit (from the main thread), Which will trigger the commit
585 // flow from the impl side.
586 layer_tree_host()->SetNeedsCommit();
587 // Then mark ourselves as not visible before processing any more messages
588 // on the main thread.
589 layer_tree_host()->SetVisible(false);
590 // If we make it without kicking a frame, we pass!
591 EndTestAfterDelay(1);
594 virtual void Layout() OVERRIDE {
595 ASSERT_FALSE(true);
596 EndTest();
599 virtual void AfterTest() OVERRIDE {}
601 private:
604 MULTI_THREAD_TEST_F(LayerTreeHostTestAbortFrameWhenInvisible);
606 // This test verifies that properties on the layer tree host are commited
607 // to the impl side.
608 class LayerTreeHostTestCommit : public LayerTreeHostTest {
609 public:
610 LayerTreeHostTestCommit() {}
612 virtual void BeginTest() OVERRIDE {
613 layer_tree_host()->SetViewportSize(gfx::Size(20, 20));
614 layer_tree_host()->set_background_color(SK_ColorGRAY);
615 layer_tree_host()->SetPageScaleFactorAndLimits(5.f, 5.f, 5.f);
617 PostSetNeedsCommitToMainThread();
620 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
621 EXPECT_EQ(gfx::Size(20, 20), impl->device_viewport_size());
622 EXPECT_EQ(SK_ColorGRAY, impl->active_tree()->background_color());
623 EXPECT_EQ(5.f, impl->active_tree()->page_scale_factor());
625 EndTest();
628 virtual void AfterTest() OVERRIDE {}
631 MULTI_THREAD_TEST_F(LayerTreeHostTestCommit);
633 // This test verifies that LayerTreeHostImpl's current frame time gets
634 // updated in consecutive frames when it doesn't draw due to tree
635 // activation failure.
636 class LayerTreeHostTestFrameTimeUpdatesAfterActivationFails
637 : public LayerTreeHostTest {
638 public:
639 LayerTreeHostTestFrameTimeUpdatesAfterActivationFails() : frame_(0) {}
641 virtual void BeginTest() OVERRIDE {
642 layer_tree_host()->SetViewportSize(gfx::Size(20, 20));
643 layer_tree_host()->set_background_color(SK_ColorGRAY);
645 PostSetNeedsCommitToMainThread();
648 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
649 if (frame_ >= 1) {
650 EXPECT_NE(first_frame_time_, impl->CurrentFrameTimeTicks());
651 EndTest();
652 return;
655 EXPECT_FALSE(impl->settings().impl_side_painting);
656 EndTest();
659 virtual bool CanActivatePendingTree(LayerTreeHostImpl* impl) OVERRIDE {
660 frame_++;
661 if (frame_ == 1) {
662 first_frame_time_ = impl->CurrentFrameTimeTicks();
664 // Since base::TimeTicks::Now() uses a low-resolution clock on
665 // Windows, we need to make sure that the clock has incremented past
666 // first_frame_time_.
667 while (first_frame_time_ == base::TimeTicks::Now()) {}
669 return false;
672 return true;
675 virtual void AfterTest() OVERRIDE {}
677 private:
678 int frame_;
679 base::TimeTicks first_frame_time_;
682 SINGLE_AND_MULTI_THREAD_TEST_F(
683 LayerTreeHostTestFrameTimeUpdatesAfterActivationFails);
685 // This test verifies that LayerTreeHostImpl's current frame time gets
686 // updated in consecutive frames when it draws in each frame.
687 class LayerTreeHostTestFrameTimeUpdatesAfterDraw : public LayerTreeHostTest {
688 public:
689 LayerTreeHostTestFrameTimeUpdatesAfterDraw() : frame_(0) {}
691 virtual void BeginTest() OVERRIDE {
692 layer_tree_host()->SetViewportSize(gfx::Size(20, 20));
693 layer_tree_host()->set_background_color(SK_ColorGRAY);
695 PostSetNeedsCommitToMainThread();
698 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
699 frame_++;
700 if (frame_ == 1) {
701 first_frame_time_ = impl->CurrentFrameTimeTicks();
702 impl->SetNeedsRedraw();
704 // Since base::TimeTicks::Now() uses a low-resolution clock on
705 // Windows, we need to make sure that the clock has incremented past
706 // first_frame_time_.
707 while (first_frame_time_ == base::TimeTicks::Now()) {}
709 return;
712 EXPECT_NE(first_frame_time_, impl->CurrentFrameTimeTicks());
713 EndTest();
716 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
717 // Ensure there isn't a commit between the two draws, to ensure that a
718 // commit isn't required for updating the current frame time. We can
719 // only check for this in the multi-threaded case, since in the single-
720 // threaded case there will always be a commit between consecutive draws.
721 if (HasImplThread())
722 EXPECT_EQ(0, frame_);
725 virtual void AfterTest() OVERRIDE {}
727 private:
728 int frame_;
729 base::TimeTicks first_frame_time_;
732 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestFrameTimeUpdatesAfterDraw);
734 // Verifies that StartPageScaleAnimation events propagate correctly
735 // from LayerTreeHost to LayerTreeHostImpl in the MT compositor.
736 class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest {
737 public:
738 LayerTreeHostTestStartPageScaleAnimation() {}
740 virtual void SetupTree() OVERRIDE {
741 LayerTreeHostTest::SetupTree();
743 scroll_layer_ = FakeContentLayer::Create(&client_);
744 scroll_layer_->SetScrollable(true);
745 scroll_layer_->SetScrollOffset(gfx::Vector2d());
746 layer_tree_host()->root_layer()->AddChild(scroll_layer_);
749 virtual void BeginTest() OVERRIDE {
750 PostSetNeedsCommitToMainThread();
753 virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta, float scale)
754 OVERRIDE {
755 gfx::Vector2d offset = scroll_layer_->scroll_offset();
756 scroll_layer_->SetScrollOffset(offset + scroll_delta);
757 layer_tree_host()->SetPageScaleFactorAndLimits(scale, 0.5f, 2.f);
760 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
761 impl->ProcessScrollDeltas();
762 // We get one commit before the first draw, and the animation doesn't happen
763 // until the second draw.
764 switch (impl->active_tree()->source_frame_number()) {
765 case 0:
766 EXPECT_EQ(1.f, impl->active_tree()->page_scale_factor());
767 // We'll start an animation when we get back to the main thread.
768 break;
769 case 1:
770 EXPECT_EQ(1.f, impl->active_tree()->page_scale_factor());
771 PostSetNeedsRedrawToMainThread();
772 break;
773 case 2:
774 EXPECT_EQ(1.25f, impl->active_tree()->page_scale_factor());
775 EndTest();
776 break;
777 default:
778 NOTREACHED();
782 virtual void DidCommitAndDrawFrame() OVERRIDE {
783 switch (layer_tree_host()->commit_number()) {
784 case 1:
785 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.5f, 2.f);
786 layer_tree_host()->StartPageScaleAnimation(
787 gfx::Vector2d(), false, 1.25f, base::TimeDelta());
788 break;
792 virtual void AfterTest() OVERRIDE {}
794 FakeContentLayerClient client_;
795 scoped_refptr<FakeContentLayer> scroll_layer_;
798 MULTI_THREAD_TEST_F(LayerTreeHostTestStartPageScaleAnimation);
800 class LayerTreeHostTestSetVisible : public LayerTreeHostTest {
801 public:
802 LayerTreeHostTestSetVisible() : num_draws_(0) {}
804 virtual void BeginTest() OVERRIDE {
805 PostSetNeedsCommitToMainThread();
806 PostSetVisibleToMainThread(false);
807 // This is suppressed while we're invisible.
808 PostSetNeedsRedrawToMainThread();
809 // Triggers the redraw.
810 PostSetVisibleToMainThread(true);
813 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
814 EXPECT_TRUE(impl->visible());
815 ++num_draws_;
816 EndTest();
819 virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, num_draws_); }
821 private:
822 int num_draws_;
825 MULTI_THREAD_TEST_F(LayerTreeHostTestSetVisible);
827 class TestOpacityChangeLayerDelegate : public ContentLayerClient {
828 public:
829 TestOpacityChangeLayerDelegate() : test_layer_(0) {}
831 void SetTestLayer(Layer* test_layer) { test_layer_ = test_layer; }
833 virtual void PaintContents(SkCanvas*, gfx::Rect, gfx::RectF*) OVERRIDE {
834 // Set layer opacity to 0.
835 if (test_layer_)
836 test_layer_->SetOpacity(0.f);
838 virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
840 private:
841 Layer* test_layer_;
844 class ContentLayerWithUpdateTracking : public ContentLayer {
845 public:
846 static scoped_refptr<ContentLayerWithUpdateTracking> Create(
847 ContentLayerClient* client) {
848 return make_scoped_refptr(new ContentLayerWithUpdateTracking(client));
851 int PaintContentsCount() { return paint_contents_count_; }
852 void ResetPaintContentsCount() { paint_contents_count_ = 0; }
854 virtual void Update(ResourceUpdateQueue* queue,
855 const OcclusionTracker* occlusion,
856 RenderingStats* stats) OVERRIDE {
857 ContentLayer::Update(queue, occlusion, stats);
858 paint_contents_count_++;
861 private:
862 explicit ContentLayerWithUpdateTracking(ContentLayerClient* client)
863 : ContentLayer(client), paint_contents_count_(0) {
864 SetAnchorPoint(gfx::PointF(0.f, 0.f));
865 SetBounds(gfx::Size(10, 10));
866 SetIsDrawable(true);
868 virtual ~ContentLayerWithUpdateTracking() {}
870 int paint_contents_count_;
873 // Layer opacity change during paint should not prevent compositor resources
874 // from being updated during commit.
875 class LayerTreeHostTestOpacityChange : public LayerTreeHostTest {
876 public:
877 LayerTreeHostTestOpacityChange()
878 : test_opacity_change_delegate_(),
879 update_check_layer_(ContentLayerWithUpdateTracking::Create(
880 &test_opacity_change_delegate_)) {
881 test_opacity_change_delegate_.SetTestLayer(update_check_layer_.get());
884 virtual void BeginTest() OVERRIDE {
885 layer_tree_host()->SetViewportSize(gfx::Size(10, 10));
886 layer_tree_host()->root_layer()->AddChild(update_check_layer_);
888 PostSetNeedsCommitToMainThread();
891 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
892 EndTest();
895 virtual void AfterTest() OVERRIDE {
896 // Update() should have been called once.
897 EXPECT_EQ(1, update_check_layer_->PaintContentsCount());
900 private:
901 TestOpacityChangeLayerDelegate test_opacity_change_delegate_;
902 scoped_refptr<ContentLayerWithUpdateTracking> update_check_layer_;
905 MULTI_THREAD_TEST_F(LayerTreeHostTestOpacityChange);
907 class NoScaleContentLayer : public ContentLayer {
908 public:
909 static scoped_refptr<NoScaleContentLayer> Create(ContentLayerClient* client) {
910 return make_scoped_refptr(new NoScaleContentLayer(client));
913 virtual void CalculateContentsScale(float ideal_contents_scale,
914 float device_scale_factor,
915 float page_scale_factor,
916 bool animating_transform_to_screen,
917 float* contents_scale_x,
918 float* contents_scale_y,
919 gfx::Size* contentBounds) OVERRIDE {
920 // Skip over the ContentLayer's method to the base Layer class.
921 Layer::CalculateContentsScale(ideal_contents_scale,
922 device_scale_factor,
923 page_scale_factor,
924 animating_transform_to_screen,
925 contents_scale_x,
926 contents_scale_y,
927 contentBounds);
930 private:
931 explicit NoScaleContentLayer(ContentLayerClient* client)
932 : ContentLayer(client) {}
933 virtual ~NoScaleContentLayer() {}
936 class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers
937 : public LayerTreeHostTest {
938 public:
939 LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers()
940 : root_layer_(NoScaleContentLayer::Create(&client_)),
941 child_layer_(ContentLayer::Create(&client_)) {}
943 virtual void BeginTest() OVERRIDE {
944 layer_tree_host()->SetViewportSize(gfx::Size(60, 60));
945 layer_tree_host()->SetDeviceScaleFactor(1.5);
946 EXPECT_EQ(gfx::Size(60, 60), layer_tree_host()->device_viewport_size());
948 root_layer_->AddChild(child_layer_);
950 root_layer_->SetIsDrawable(true);
951 root_layer_->SetBounds(gfx::Size(30, 30));
952 root_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
954 child_layer_->SetIsDrawable(true);
955 child_layer_->SetPosition(gfx::Point(2, 2));
956 child_layer_->SetBounds(gfx::Size(10, 10));
957 child_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
959 layer_tree_host()->SetRootLayer(root_layer_);
961 PostSetNeedsCommitToMainThread();
964 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
965 // Should only do one commit.
966 EXPECT_EQ(0, impl->active_tree()->source_frame_number());
967 // Device scale factor should come over to impl.
968 EXPECT_NEAR(impl->device_scale_factor(), 1.5f, 0.00001f);
970 // Both layers are on impl.
971 ASSERT_EQ(1u, impl->active_tree()->root_layer()->children().size());
973 // Device viewport is scaled.
974 EXPECT_EQ(gfx::Size(60, 60), impl->device_viewport_size());
976 LayerImpl* root = impl->active_tree()->root_layer();
977 LayerImpl* child = impl->active_tree()->root_layer()->children()[0];
979 // Positions remain in layout pixels.
980 EXPECT_EQ(gfx::Point(0, 0), root->position());
981 EXPECT_EQ(gfx::Point(2, 2), child->position());
983 // Compute all the layer transforms for the frame.
984 LayerTreeHostImpl::FrameData frame_data;
985 impl->PrepareToDraw(&frame_data, gfx::Rect());
986 impl->DidDrawAllLayers(frame_data);
988 const LayerImplList& render_surface_layer_list =
989 *frame_data.render_surface_layer_list;
991 // Both layers should be drawing into the root render surface.
992 ASSERT_EQ(1u, render_surface_layer_list.size());
993 ASSERT_EQ(root->render_surface(),
994 render_surface_layer_list[0]->render_surface());
995 ASSERT_EQ(2u, root->render_surface()->layer_list().size());
997 // The root render surface is the size of the viewport.
998 EXPECT_RECT_EQ(gfx::Rect(0, 0, 60, 60),
999 root->render_surface()->content_rect());
1001 // The content bounds of the child should be scaled.
1002 gfx::Size child_bounds_scaled =
1003 gfx::ToCeiledSize(gfx::ScaleSize(child->bounds(), 1.5));
1004 EXPECT_EQ(child_bounds_scaled, child->content_bounds());
1006 gfx::Transform scale_transform;
1007 scale_transform.Scale(impl->device_scale_factor(),
1008 impl->device_scale_factor());
1010 // The root layer is scaled by 2x.
1011 gfx::Transform root_screen_space_transform = scale_transform;
1012 gfx::Transform root_draw_transform = scale_transform;
1014 EXPECT_EQ(root_draw_transform, root->draw_transform());
1015 EXPECT_EQ(root_screen_space_transform, root->screen_space_transform());
1017 // The child is at position 2,2, which is transformed to 3,3 after the scale
1018 gfx::Transform child_screen_space_transform;
1019 child_screen_space_transform.Translate(3.f, 3.f);
1020 gfx::Transform child_draw_transform = child_screen_space_transform;
1022 EXPECT_TRANSFORMATION_MATRIX_EQ(child_draw_transform,
1023 child->draw_transform());
1024 EXPECT_TRANSFORMATION_MATRIX_EQ(child_screen_space_transform,
1025 child->screen_space_transform());
1027 EndTest();
1030 virtual void AfterTest() OVERRIDE {}
1032 private:
1033 FakeContentLayerClient client_;
1034 scoped_refptr<NoScaleContentLayer> root_layer_;
1035 scoped_refptr<ContentLayer> child_layer_;
1038 MULTI_THREAD_TEST_F(LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers);
1040 // Verify atomicity of commits and reuse of textures.
1041 class LayerTreeHostTestAtomicCommit : public LayerTreeHostTest {
1042 public:
1043 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1044 // Make sure partial texture updates are turned off.
1045 settings->max_partial_texture_updates = 0;
1046 // Linear fade animator prevents scrollbars from drawing immediately.
1047 settings->use_linear_fade_scrollbar_animator = false;
1050 virtual void SetupTree() OVERRIDE {
1051 layer_ = FakeContentLayer::Create(&client_);
1052 layer_->SetBounds(gfx::Size(10, 20));
1054 bool paint_scrollbar = true;
1055 bool has_thumb = false;
1056 scrollbar_ =
1057 FakeScrollbarLayer::Create(paint_scrollbar, has_thumb, layer_->id());
1058 scrollbar_->SetPosition(gfx::Point(0, 10));
1059 scrollbar_->SetBounds(gfx::Size(10, 10));
1061 layer_->AddChild(scrollbar_);
1063 layer_tree_host()->SetRootLayer(layer_);
1064 LayerTreeHostTest::SetupTree();
1067 virtual void BeginTest() OVERRIDE {
1068 drew_frame_ = -1;
1069 PostSetNeedsCommitToMainThread();
1072 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1073 ASSERT_EQ(0u, layer_tree_host()->settings().max_partial_texture_updates);
1075 TestWebGraphicsContext3D* context = static_cast<TestWebGraphicsContext3D*>(
1076 impl->output_surface()->context3d());
1078 switch (impl->active_tree()->source_frame_number()) {
1079 case 0:
1080 // Number of textures should be one for each layer
1081 ASSERT_EQ(2u, context->NumTextures());
1082 // Number of textures used for commit should be one for each layer.
1083 EXPECT_EQ(2u, context->NumUsedTextures());
1084 // Verify that used texture is correct.
1085 EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
1086 EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
1088 context->ResetUsedTextures();
1089 PostSetNeedsCommitToMainThread();
1090 break;
1091 case 1:
1092 // Number of textures should be doubled as the first textures
1093 // are used by impl thread and cannot by used for update.
1094 ASSERT_EQ(4u, context->NumTextures());
1095 // Number of textures used for commit should still be
1096 // one for each layer.
1097 EXPECT_EQ(2u, context->NumUsedTextures());
1098 // First textures should not have been used.
1099 EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
1100 EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
1101 // New textures should have been used.
1102 EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
1103 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1105 context->ResetUsedTextures();
1106 PostSetNeedsCommitToMainThread();
1107 break;
1108 case 2:
1109 EndTest();
1110 break;
1111 default:
1112 NOTREACHED();
1113 break;
1117 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1118 TestWebGraphicsContext3D* context = static_cast<TestWebGraphicsContext3D*>(
1119 impl->output_surface()->context3d());
1121 if (drew_frame_ == impl->active_tree()->source_frame_number()) {
1122 EXPECT_EQ(0u, context->NumUsedTextures()) << "For frame " << drew_frame_;
1123 return;
1125 drew_frame_ = impl->active_tree()->source_frame_number();
1127 // We draw/ship one texture each frame for each layer.
1128 EXPECT_EQ(2u, context->NumUsedTextures());
1129 context->ResetUsedTextures();
1132 virtual void Layout() OVERRIDE {
1133 layer_->SetNeedsDisplay();
1134 scrollbar_->SetNeedsDisplay();
1137 virtual void AfterTest() OVERRIDE {}
1139 private:
1140 FakeContentLayerClient client_;
1141 scoped_refptr<FakeContentLayer> layer_;
1142 scoped_refptr<FakeScrollbarLayer> scrollbar_;
1143 int drew_frame_;
1146 MULTI_THREAD_TEST_F(LayerTreeHostTestAtomicCommit);
1148 static void SetLayerPropertiesForTesting(Layer* layer,
1149 Layer* parent,
1150 const gfx::Transform& transform,
1151 gfx::PointF anchor,
1152 gfx::PointF position,
1153 gfx::Size bounds,
1154 bool opaque) {
1155 layer->RemoveAllChildren();
1156 if (parent)
1157 parent->AddChild(layer);
1158 layer->SetTransform(transform);
1159 layer->SetAnchorPoint(anchor);
1160 layer->SetPosition(position);
1161 layer->SetBounds(bounds);
1162 layer->SetContentsOpaque(opaque);
1165 class LayerTreeHostTestAtomicCommitWithPartialUpdate
1166 : public LayerTreeHostTest {
1167 public:
1168 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1169 // Allow one partial texture update.
1170 settings->max_partial_texture_updates = 1;
1171 // Linear fade animator prevents scrollbars from drawing immediately.
1172 settings->use_linear_fade_scrollbar_animator = false;
1173 // No partial updates when impl side painting is enabled.
1174 settings->impl_side_painting = false;
1177 virtual void SetupTree() OVERRIDE {
1178 parent_ = FakeContentLayer::Create(&client_);
1179 parent_->SetBounds(gfx::Size(10, 20));
1181 child_ = FakeContentLayer::Create(&client_);
1182 child_->SetPosition(gfx::Point(0, 10));
1183 child_->SetBounds(gfx::Size(3, 10));
1185 bool paint_scrollbar = true;
1186 bool has_thumb = false;
1187 scrollbar_with_paints_ =
1188 FakeScrollbarLayer::Create(paint_scrollbar, has_thumb, parent_->id());
1189 scrollbar_with_paints_->SetPosition(gfx::Point(3, 10));
1190 scrollbar_with_paints_->SetBounds(gfx::Size(3, 10));
1192 paint_scrollbar = false;
1193 scrollbar_without_paints_ =
1194 FakeScrollbarLayer::Create(paint_scrollbar, has_thumb, parent_->id());
1195 scrollbar_without_paints_->SetPosition(gfx::Point(6, 10));
1196 scrollbar_without_paints_->SetBounds(gfx::Size(3, 10));
1198 parent_->AddChild(child_);
1199 parent_->AddChild(scrollbar_with_paints_);
1200 parent_->AddChild(scrollbar_without_paints_);
1202 layer_tree_host()->SetRootLayer(parent_);
1203 LayerTreeHostTest::SetupTree();
1206 virtual void BeginTest() OVERRIDE {
1207 PostSetNeedsCommitToMainThread();
1210 virtual void DidCommitAndDrawFrame() OVERRIDE {
1211 switch (layer_tree_host()->commit_number()) {
1212 case 1:
1213 parent_->SetNeedsDisplay();
1214 child_->SetNeedsDisplay();
1215 scrollbar_with_paints_->SetNeedsDisplay();
1216 scrollbar_without_paints_->SetNeedsDisplay();
1217 break;
1218 case 2:
1219 // Damage part of layers.
1220 parent_->SetNeedsDisplayRect(gfx::RectF(0.f, 0.f, 5.f, 5.f));
1221 child_->SetNeedsDisplayRect(gfx::RectF(0.f, 0.f, 5.f, 5.f));
1222 scrollbar_with_paints_->SetNeedsDisplayRect(
1223 gfx::RectF(0.f, 0.f, 5.f, 5.f));
1224 scrollbar_without_paints_->SetNeedsDisplayRect(
1225 gfx::RectF(0.f, 0.f, 5.f, 5.f));
1226 break;
1227 case 3:
1228 child_->SetNeedsDisplay();
1229 scrollbar_with_paints_->SetNeedsDisplay();
1230 scrollbar_without_paints_->SetNeedsDisplay();
1231 layer_tree_host()->SetViewportSize(gfx::Size(10, 10));
1232 break;
1233 case 4:
1234 layer_tree_host()->SetViewportSize(gfx::Size(10, 20));
1235 break;
1236 case 5:
1237 EndTest();
1238 break;
1239 default:
1240 NOTREACHED() << layer_tree_host()->commit_number();
1241 break;
1245 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1246 ASSERT_EQ(1u, layer_tree_host()->settings().max_partial_texture_updates);
1248 TestWebGraphicsContext3D* context = static_cast<TestWebGraphicsContext3D*>(
1249 impl->output_surface()->context3d());
1251 switch (impl->active_tree()->source_frame_number()) {
1252 case 0:
1253 // Number of textures should be one for each layer.
1254 ASSERT_EQ(4u, context->NumTextures());
1255 // Number of textures used for commit should be one for each layer.
1256 EXPECT_EQ(4u, context->NumUsedTextures());
1257 // Verify that used textures are correct.
1258 EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
1259 EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
1260 EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
1261 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1263 context->ResetUsedTextures();
1264 break;
1265 case 1:
1266 // Number of textures should be two for each content layer and one
1267 // for each scrollbar, since they always do a partial update.
1268 ASSERT_EQ(6u, context->NumTextures());
1269 // Number of textures used for commit should be one for each content
1270 // layer, and one for the scrollbar layer that paints.
1271 EXPECT_EQ(3u, context->NumUsedTextures());
1273 // First content textures should not have been used.
1274 EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
1275 EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
1276 // The non-painting scrollbar's texture wasn't updated.
1277 EXPECT_FALSE(context->UsedTexture(context->TextureAt(2)));
1278 // The painting scrollbar's partial update texture was used.
1279 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1280 // New textures should have been used.
1281 EXPECT_TRUE(context->UsedTexture(context->TextureAt(4)));
1282 EXPECT_TRUE(context->UsedTexture(context->TextureAt(5)));
1284 context->ResetUsedTextures();
1285 break;
1286 case 2:
1287 // Number of textures should be two for each content layer and one
1288 // for each scrollbar, since they always do a partial update.
1289 ASSERT_EQ(6u, context->NumTextures());
1290 // Number of textures used for commit should be one for each content
1291 // layer, and one for the scrollbar layer that paints.
1292 EXPECT_EQ(3u, context->NumUsedTextures());
1294 // The non-painting scrollbar's texture wasn't updated.
1295 EXPECT_FALSE(context->UsedTexture(context->TextureAt(2)));
1296 // The painting scrollbar does a partial update.
1297 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1298 // One content layer does a partial update also.
1299 EXPECT_TRUE(context->UsedTexture(context->TextureAt(4)));
1300 EXPECT_FALSE(context->UsedTexture(context->TextureAt(5)));
1302 context->ResetUsedTextures();
1303 break;
1304 case 3:
1305 // No textures should be used for commit.
1306 EXPECT_EQ(0u, context->NumUsedTextures());
1308 context->ResetUsedTextures();
1309 break;
1310 case 4:
1311 // Number of textures used for commit should be two. One for the
1312 // content layer, and one for the painting scrollbar. The
1313 // non-painting scrollbar doesn't update its texture.
1314 EXPECT_EQ(2u, context->NumUsedTextures());
1316 context->ResetUsedTextures();
1317 break;
1318 default:
1319 NOTREACHED();
1320 break;
1324 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1325 EXPECT_LT(impl->active_tree()->source_frame_number(), 5);
1327 TestWebGraphicsContext3D* context = static_cast<TestWebGraphicsContext3D*>(
1328 impl->output_surface()->context3d());
1330 // Number of textures used for drawing should one per layer except for
1331 // frame 3 where the viewport only contains one layer.
1332 if (impl->active_tree()->source_frame_number() == 3) {
1333 EXPECT_EQ(1u, context->NumUsedTextures());
1334 } else {
1335 EXPECT_EQ(4u, context->NumUsedTextures()) <<
1336 "For frame " << impl->active_tree()->source_frame_number();
1339 context->ResetUsedTextures();
1342 virtual void AfterTest() OVERRIDE {}
1344 private:
1345 FakeContentLayerClient client_;
1346 scoped_refptr<FakeContentLayer> parent_;
1347 scoped_refptr<FakeContentLayer> child_;
1348 scoped_refptr<FakeScrollbarLayer> scrollbar_with_paints_;
1349 scoped_refptr<FakeScrollbarLayer> scrollbar_without_paints_;
1352 // Partial updates are not possible with a delegating renderer.
1353 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1354 LayerTreeHostTestAtomicCommitWithPartialUpdate);
1356 class LayerTreeHostTestFinishAllRendering : public LayerTreeHostTest {
1357 public:
1358 LayerTreeHostTestFinishAllRendering() : once_(false), draw_count_(0) {}
1360 virtual void BeginTest() OVERRIDE {
1361 layer_tree_host()->SetNeedsRedraw();
1362 PostSetNeedsCommitToMainThread();
1365 virtual void DidCommitAndDrawFrame() OVERRIDE {
1366 if (once_)
1367 return;
1368 once_ = true;
1369 layer_tree_host()->SetNeedsRedraw();
1370 layer_tree_host()->AcquireLayerTextures();
1372 base::AutoLock lock(lock_);
1373 draw_count_ = 0;
1375 layer_tree_host()->FinishAllRendering();
1377 base::AutoLock lock(lock_);
1378 EXPECT_EQ(0, draw_count_);
1380 EndTest();
1383 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1384 base::AutoLock lock(lock_);
1385 ++draw_count_;
1388 virtual void AfterTest() OVERRIDE {}
1390 private:
1391 bool once_;
1392 base::Lock lock_;
1393 int draw_count_;
1396 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestFinishAllRendering);
1398 class LayerTreeHostTestCompositeAndReadbackCleanup : public LayerTreeHostTest {
1399 public:
1400 virtual void BeginTest() OVERRIDE {
1401 Layer* root_layer = layer_tree_host()->root_layer();
1403 char pixels[4];
1404 layer_tree_host()->CompositeAndReadback(static_cast<void*>(&pixels),
1405 gfx::Rect(0, 0, 1, 1));
1406 EXPECT_FALSE(root_layer->render_surface());
1408 EndTest();
1411 virtual void AfterTest() OVERRIDE {}
1414 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestCompositeAndReadbackCleanup);
1416 class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit
1417 : public LayerTreeHostTest {
1418 public:
1419 LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit()
1420 : root_layer_(FakeContentLayer::Create(&client_)),
1421 surface_layer1_(
1422 FakeContentLayer::Create(&client_)),
1423 replica_layer1_(
1424 FakeContentLayer::Create(&client_)),
1425 surface_layer2_(
1426 FakeContentLayer::Create(&client_)),
1427 replica_layer2_(
1428 FakeContentLayer::Create(&client_)) {}
1430 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1431 settings->cache_render_pass_contents = true;
1434 virtual void BeginTest() OVERRIDE {
1435 layer_tree_host()->SetViewportSize(gfx::Size(100, 100));
1437 root_layer_->SetBounds(gfx::Size(100, 100));
1438 surface_layer1_->SetBounds(gfx::Size(100, 100));
1439 surface_layer1_->SetForceRenderSurface(true);
1440 surface_layer1_->SetOpacity(0.5f);
1441 surface_layer2_->SetBounds(gfx::Size(100, 100));
1442 surface_layer2_->SetForceRenderSurface(true);
1443 surface_layer2_->SetOpacity(0.5f);
1445 surface_layer1_->SetReplicaLayer(replica_layer1_.get());
1446 surface_layer2_->SetReplicaLayer(replica_layer2_.get());
1448 root_layer_->AddChild(surface_layer1_);
1449 surface_layer1_->AddChild(surface_layer2_);
1450 layer_tree_host()->SetRootLayer(root_layer_);
1452 PostSetNeedsCommitToMainThread();
1455 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
1456 Renderer* renderer = host_impl->renderer();
1457 RenderPass::Id surface1_render_pass_id = host_impl->active_tree()
1458 ->root_layer()->children()[0]->render_surface()->RenderPassId();
1459 RenderPass::Id surface2_render_pass_id =
1460 host_impl->active_tree()->root_layer()->children()[0]->children()[0]
1461 ->render_surface()->RenderPassId();
1463 switch (host_impl->active_tree()->source_frame_number()) {
1464 case 0:
1465 EXPECT_TRUE(renderer->HaveCachedResourcesForRenderPassId(
1466 surface1_render_pass_id));
1467 EXPECT_TRUE(renderer->HaveCachedResourcesForRenderPassId(
1468 surface2_render_pass_id));
1470 // Reduce the memory limit to only fit the root layer and one render
1471 // surface. This prevents any contents drawing into surfaces
1472 // from being allocated.
1473 host_impl->SetManagedMemoryPolicy(
1474 ManagedMemoryPolicy(100 * 100 * 4 * 2));
1475 break;
1476 case 1:
1477 EXPECT_FALSE(renderer->HaveCachedResourcesForRenderPassId(
1478 surface1_render_pass_id));
1479 EXPECT_FALSE(renderer->HaveCachedResourcesForRenderPassId(
1480 surface2_render_pass_id));
1482 EndTest();
1483 break;
1487 virtual void DidCommitAndDrawFrame() OVERRIDE {
1488 if (!TestEnded())
1489 root_layer_->SetNeedsDisplay();
1492 virtual void AfterTest() OVERRIDE {
1493 EXPECT_EQ(3u, root_layer_->update_count());
1494 EXPECT_EQ(3u, surface_layer1_->update_count());
1495 EXPECT_EQ(3u, surface_layer2_->update_count());
1498 private:
1499 FakeContentLayerClient client_;
1500 scoped_refptr<FakeContentLayer> root_layer_;
1501 scoped_refptr<FakeContentLayer> surface_layer1_;
1502 scoped_refptr<FakeContentLayer> replica_layer1_;
1503 scoped_refptr<FakeContentLayer> surface_layer2_;
1504 scoped_refptr<FakeContentLayer> replica_layer2_;
1507 // Surfaces don't exist with a delegated renderer.
1508 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
1509 LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit);
1511 class EvictionTestLayer : public Layer {
1512 public:
1513 static scoped_refptr<EvictionTestLayer> Create() {
1514 return make_scoped_refptr(new EvictionTestLayer());
1517 virtual void Update(ResourceUpdateQueue*,
1518 const OcclusionTracker*,
1519 RenderingStats*) OVERRIDE;
1520 virtual bool DrawsContent() const OVERRIDE { return true; }
1522 virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl)
1523 OVERRIDE;
1524 virtual void PushPropertiesTo(LayerImpl* impl) OVERRIDE;
1525 virtual void SetTexturePriorities(const PriorityCalculator&) OVERRIDE;
1527 bool HaveBackingTexture() const {
1528 return texture_.get() ? texture_->have_backing_texture() : false;
1531 private:
1532 EvictionTestLayer() : Layer() {}
1533 virtual ~EvictionTestLayer() {}
1535 void CreateTextureIfNeeded() {
1536 if (texture_)
1537 return;
1538 texture_ = PrioritizedResource::Create(
1539 layer_tree_host()->contents_texture_manager());
1540 texture_->SetDimensions(gfx::Size(10, 10), GL_RGBA);
1541 bitmap_.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
1544 scoped_ptr<PrioritizedResource> texture_;
1545 SkBitmap bitmap_;
1548 class EvictionTestLayerImpl : public LayerImpl {
1549 public:
1550 static scoped_ptr<EvictionTestLayerImpl> Create(LayerTreeImpl* tree_impl,
1551 int id) {
1552 return make_scoped_ptr(new EvictionTestLayerImpl(tree_impl, id));
1554 virtual ~EvictionTestLayerImpl() {}
1556 virtual void AppendQuads(QuadSink* quad_sink,
1557 AppendQuadsData* append_quads_data) OVERRIDE {
1558 ASSERT_TRUE(has_texture_);
1559 ASSERT_NE(0u, layer_tree_impl()->resource_provider()->num_resources());
1562 void SetHasTexture(bool has_texture) { has_texture_ = has_texture; }
1564 private:
1565 EvictionTestLayerImpl(LayerTreeImpl* tree_impl, int id)
1566 : LayerImpl(tree_impl, id), has_texture_(false) {}
1568 bool has_texture_;
1571 void EvictionTestLayer::SetTexturePriorities(const PriorityCalculator&) {
1572 CreateTextureIfNeeded();
1573 if (!texture_)
1574 return;
1575 texture_->set_request_priority(PriorityCalculator::UIPriority(true));
1578 void EvictionTestLayer::Update(ResourceUpdateQueue* queue,
1579 const OcclusionTracker*,
1580 RenderingStats*) {
1581 CreateTextureIfNeeded();
1582 if (!texture_)
1583 return;
1585 gfx::Rect full_rect(0, 0, 10, 10);
1586 ResourceUpdate upload = ResourceUpdate::Create(
1587 texture_.get(), &bitmap_, full_rect, full_rect, gfx::Vector2d());
1588 queue->AppendFullUpload(upload);
1591 scoped_ptr<LayerImpl> EvictionTestLayer::CreateLayerImpl(
1592 LayerTreeImpl* tree_impl) {
1593 return EvictionTestLayerImpl::Create(tree_impl, layer_id_)
1594 .PassAs<LayerImpl>();
1597 void EvictionTestLayer::PushPropertiesTo(LayerImpl* layer_impl) {
1598 Layer::PushPropertiesTo(layer_impl);
1600 EvictionTestLayerImpl* test_layer_impl =
1601 static_cast<EvictionTestLayerImpl*>(layer_impl);
1602 test_layer_impl->SetHasTexture(texture_->have_backing_texture());
1605 class LayerTreeHostTestEvictTextures : public LayerTreeHostTest {
1606 public:
1607 LayerTreeHostTestEvictTextures()
1608 : layer_(EvictionTestLayer::Create()),
1609 impl_for_evict_textures_(0),
1610 num_commits_(0) {}
1612 virtual void BeginTest() OVERRIDE {
1613 layer_tree_host()->SetRootLayer(layer_);
1614 layer_tree_host()->SetViewportSize(gfx::Size(10, 20));
1616 gfx::Transform identity_matrix;
1617 SetLayerPropertiesForTesting(layer_.get(),
1619 identity_matrix,
1620 gfx::PointF(0.f, 0.f),
1621 gfx::PointF(0.f, 0.f),
1622 gfx::Size(10, 20),
1623 true);
1625 PostSetNeedsCommitToMainThread();
1628 void PostEvictTextures() {
1629 DCHECK(HasImplThread());
1630 ImplThreadTaskRunner()->PostTask(
1631 FROM_HERE,
1632 base::Bind(&LayerTreeHostTestEvictTextures::EvictTexturesOnImplThread,
1633 base::Unretained(this)));
1636 void EvictTexturesOnImplThread() {
1637 DCHECK(impl_for_evict_textures_);
1638 impl_for_evict_textures_->EnforceManagedMemoryPolicy(
1639 ManagedMemoryPolicy(0));
1642 // Commit 1: Just commit and draw normally, then post an eviction at the end
1643 // that will trigger a commit.
1644 // Commit 2: Triggered by the eviction, let it go through and then set
1645 // needsCommit.
1646 // Commit 3: Triggered by the setNeedsCommit. In Layout(), post an eviction
1647 // task, which will be handled before the commit. Don't set needsCommit, it
1648 // should have been posted. A frame should not be drawn (note,
1649 // didCommitAndDrawFrame may be called anyway).
1650 // Commit 4: Triggered by the eviction, let it go through and then set
1651 // needsCommit.
1652 // Commit 5: Triggered by the setNeedsCommit, post an eviction task in
1653 // Layout(), a frame should not be drawn but a commit will be posted.
1654 // Commit 6: Triggered by the eviction, post an eviction task in
1655 // Layout(), which will be a noop, letting the commit (which recreates the
1656 // textures) go through and draw a frame, then end the test.
1658 // Commits 1+2 test the eviction recovery path where eviction happens outside
1659 // of the beginFrame/commit pair.
1660 // Commits 3+4 test the eviction recovery path where eviction happens inside
1661 // the beginFrame/commit pair.
1662 // Commits 5+6 test the path where an eviction happens during the eviction
1663 // recovery path.
1664 virtual void DidCommit() OVERRIDE {
1665 switch (num_commits_) {
1666 case 1:
1667 EXPECT_TRUE(layer_->HaveBackingTexture());
1668 PostEvictTextures();
1669 break;
1670 case 2:
1671 EXPECT_TRUE(layer_->HaveBackingTexture());
1672 layer_tree_host()->SetNeedsCommit();
1673 break;
1674 case 3:
1675 break;
1676 case 4:
1677 EXPECT_TRUE(layer_->HaveBackingTexture());
1678 layer_tree_host()->SetNeedsCommit();
1679 break;
1680 case 5:
1681 break;
1682 case 6:
1683 EXPECT_TRUE(layer_->HaveBackingTexture());
1684 EndTest();
1685 break;
1686 default:
1687 NOTREACHED();
1688 break;
1692 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1693 impl_for_evict_textures_ = impl;
1696 virtual void Layout() OVERRIDE {
1697 ++num_commits_;
1698 switch (num_commits_) {
1699 case 1:
1700 case 2:
1701 break;
1702 case 3:
1703 PostEvictTextures();
1704 break;
1705 case 4:
1706 // We couldn't check in didCommitAndDrawFrame on commit 3,
1707 // so check here.
1708 EXPECT_FALSE(layer_->HaveBackingTexture());
1709 break;
1710 case 5:
1711 PostEvictTextures();
1712 break;
1713 case 6:
1714 // We couldn't check in didCommitAndDrawFrame on commit 5,
1715 // so check here.
1716 EXPECT_FALSE(layer_->HaveBackingTexture());
1717 PostEvictTextures();
1718 break;
1719 default:
1720 NOTREACHED();
1721 break;
1725 virtual void AfterTest() OVERRIDE {}
1727 private:
1728 FakeContentLayerClient client_;
1729 scoped_refptr<EvictionTestLayer> layer_;
1730 LayerTreeHostImpl* impl_for_evict_textures_;
1731 int num_commits_;
1734 MULTI_THREAD_TEST_F(LayerTreeHostTestEvictTextures);
1736 class LayerTreeHostTestContinuousCommit : public LayerTreeHostTest {
1737 public:
1738 LayerTreeHostTestContinuousCommit()
1739 : num_commit_complete_(0), num_draw_layers_(0) {}
1741 virtual void BeginTest() OVERRIDE {
1742 layer_tree_host()->SetViewportSize(gfx::Size(10, 10));
1743 layer_tree_host()->root_layer()->SetBounds(gfx::Size(10, 10));
1745 PostSetNeedsCommitToMainThread();
1748 virtual void DidCommit() OVERRIDE {
1749 if (num_draw_layers_ == 2)
1750 return;
1751 layer_tree_host()->root_layer()->SetNeedsDisplay();
1754 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1755 if (num_draw_layers_ == 1)
1756 num_commit_complete_++;
1759 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1760 num_draw_layers_++;
1761 if (num_draw_layers_ == 2)
1762 EndTest();
1765 virtual void AfterTest() OVERRIDE {
1766 // Check that we didn't commit twice between first and second draw.
1767 EXPECT_EQ(1, num_commit_complete_);
1770 private:
1771 int num_commit_complete_;
1772 int num_draw_layers_;
1775 MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousCommit);
1777 class LayerTreeHostTestContinuousInvalidate : public LayerTreeHostTest {
1778 public:
1779 LayerTreeHostTestContinuousInvalidate()
1780 : num_commit_complete_(0), num_draw_layers_(0) {}
1782 virtual void BeginTest() OVERRIDE {
1783 layer_tree_host()->SetViewportSize(gfx::Size(10, 10));
1784 layer_tree_host()->root_layer()->SetBounds(gfx::Size(10, 10));
1786 content_layer_ = ContentLayer::Create(&client_);
1787 content_layer_->SetBounds(gfx::Size(10, 10));
1788 content_layer_->SetPosition(gfx::PointF(0.f, 0.f));
1789 content_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
1790 content_layer_->SetIsDrawable(true);
1791 layer_tree_host()->root_layer()->AddChild(content_layer_);
1793 PostSetNeedsCommitToMainThread();
1796 virtual void DidCommitAndDrawFrame() OVERRIDE {
1797 if (num_draw_layers_ == 2)
1798 return;
1799 content_layer_->SetNeedsDisplay();
1802 virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1803 if (num_draw_layers_ == 1)
1804 num_commit_complete_++;
1807 virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
1808 num_draw_layers_++;
1809 if (num_draw_layers_ == 2)
1810 EndTest();
1813 virtual void AfterTest() OVERRIDE {
1814 // Check that we didn't commit twice between first and second draw.
1815 EXPECT_EQ(1, num_commit_complete_);
1818 private:
1819 FakeContentLayerClient client_;
1820 scoped_refptr<Layer> content_layer_;
1821 int num_commit_complete_;
1822 int num_draw_layers_;
1825 MULTI_THREAD_TEST_F(LayerTreeHostTestContinuousInvalidate);
1827 class LayerTreeHostTestDeferCommits : public LayerTreeHostTest {
1828 public:
1829 LayerTreeHostTestDeferCommits()
1830 : num_commits_deferred_(0), num_complete_commits_(0) {}
1832 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
1834 virtual void DidDeferCommit() OVERRIDE {
1835 num_commits_deferred_++;
1836 layer_tree_host()->SetDeferCommits(false);
1839 virtual void DidCommit() OVERRIDE {
1840 num_complete_commits_++;
1841 switch (num_complete_commits_) {
1842 case 1:
1843 EXPECT_EQ(0, num_commits_deferred_);
1844 layer_tree_host()->SetDeferCommits(true);
1845 PostSetNeedsCommitToMainThread();
1846 break;
1847 case 2:
1848 EndTest();
1849 break;
1850 default:
1851 NOTREACHED();
1852 break;
1856 virtual void AfterTest() OVERRIDE {
1857 EXPECT_EQ(1, num_commits_deferred_);
1858 EXPECT_EQ(2, num_complete_commits_);
1861 private:
1862 int num_commits_deferred_;
1863 int num_complete_commits_;
1866 MULTI_THREAD_TEST_F(LayerTreeHostTestDeferCommits);
1868 class LayerTreeHostWithProxy : public LayerTreeHost {
1869 public:
1870 LayerTreeHostWithProxy(FakeLayerTreeHostClient* client,
1871 const LayerTreeSettings& settings,
1872 scoped_ptr<FakeProxy> proxy)
1873 : LayerTreeHost(client, settings) {
1874 proxy->SetLayerTreeHost(this);
1875 EXPECT_TRUE(InitializeForTesting(proxy.PassAs<Proxy>()));
1879 TEST(LayerTreeHostTest, LimitPartialUpdates) {
1880 // When partial updates are not allowed, max updates should be 0.
1882 FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
1884 scoped_ptr<FakeProxy> proxy(new FakeProxy);
1885 proxy->GetRendererCapabilities().allow_partial_texture_updates = false;
1886 proxy->SetMaxPartialTextureUpdates(5);
1888 LayerTreeSettings settings;
1889 settings.max_partial_texture_updates = 10;
1891 LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
1892 EXPECT_TRUE(host.InitializeOutputSurfaceIfNeeded());
1894 EXPECT_EQ(0u, host.settings().max_partial_texture_updates);
1897 // When partial updates are allowed,
1898 // max updates should be limited by the proxy.
1900 FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
1902 scoped_ptr<FakeProxy> proxy(new FakeProxy);
1903 proxy->GetRendererCapabilities().allow_partial_texture_updates = true;
1904 proxy->SetMaxPartialTextureUpdates(5);
1906 LayerTreeSettings settings;
1907 settings.max_partial_texture_updates = 10;
1909 LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
1910 EXPECT_TRUE(host.InitializeOutputSurfaceIfNeeded());
1912 EXPECT_EQ(5u, host.settings().max_partial_texture_updates);
1915 // When partial updates are allowed,
1916 // max updates should also be limited by the settings.
1918 FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
1920 scoped_ptr<FakeProxy> proxy(new FakeProxy);
1921 proxy->GetRendererCapabilities().allow_partial_texture_updates = true;
1922 proxy->SetMaxPartialTextureUpdates(20);
1924 LayerTreeSettings settings;
1925 settings.max_partial_texture_updates = 10;
1927 LayerTreeHostWithProxy host(&client, settings, proxy.Pass());
1928 EXPECT_TRUE(host.InitializeOutputSurfaceIfNeeded());
1930 EXPECT_EQ(10u, host.settings().max_partial_texture_updates);
1934 TEST(LayerTreeHostTest, PartialUpdatesWithGLRenderer) {
1935 FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
1937 LayerTreeSettings settings;
1938 settings.max_partial_texture_updates = 4;
1940 scoped_ptr<LayerTreeHost> host =
1941 LayerTreeHost::Create(&client, settings, NULL);
1942 EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
1943 EXPECT_EQ(4u, host->settings().max_partial_texture_updates);
1946 TEST(LayerTreeHostTest, PartialUpdatesWithSoftwareRenderer) {
1947 FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_SOFTWARE);
1949 LayerTreeSettings settings;
1950 settings.max_partial_texture_updates = 4;
1952 scoped_ptr<LayerTreeHost> host =
1953 LayerTreeHost::Create(&client, settings, NULL);
1954 EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
1955 EXPECT_EQ(4u, host->settings().max_partial_texture_updates);
1958 TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndGLContent) {
1959 FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DELEGATED_3D);
1961 LayerTreeSettings settings;
1962 settings.max_partial_texture_updates = 4;
1964 scoped_ptr<LayerTreeHost> host =
1965 LayerTreeHost::Create(&client, settings, NULL);
1966 EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
1967 EXPECT_EQ(0u, host->settings().max_partial_texture_updates);
1970 TEST(LayerTreeHostTest,
1971 PartialUpdatesWithDelegatingRendererAndSoftwareContent) {
1972 FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DELEGATED_SOFTWARE);
1974 LayerTreeSettings settings;
1975 settings.max_partial_texture_updates = 4;
1977 scoped_ptr<LayerTreeHost> host =
1978 LayerTreeHost::Create(&client, settings, NULL);
1979 EXPECT_TRUE(host->InitializeOutputSurfaceIfNeeded());
1980 EXPECT_EQ(0u, host->settings().max_partial_texture_updates);
1983 class LayerTreeHostTestCapturePicture : public LayerTreeHostTest {
1984 public:
1985 LayerTreeHostTestCapturePicture()
1986 : bounds_(gfx::Size(100, 100)),
1987 layer_(PictureLayer::Create(&content_client_)) {}
1989 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
1990 settings->impl_side_painting = true;
1993 class FillRectContentLayerClient : public ContentLayerClient {
1994 public:
1995 virtual void PaintContents(SkCanvas* canvas,
1996 gfx::Rect clip,
1997 gfx::RectF* opaque) OVERRIDE {
1998 SkPaint paint;
1999 paint.setColor(SK_ColorGREEN);
2001 SkRect rect = SkRect::MakeWH(canvas->getDeviceSize().width(),
2002 canvas->getDeviceSize().height());
2003 *opaque = gfx::RectF(rect.width(), rect.height());
2004 canvas->drawRect(rect, paint);
2006 virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
2009 virtual void BeginTest() OVERRIDE {
2010 layer_->SetIsDrawable(true);
2011 layer_->SetBounds(bounds_);
2012 // Outside viewport so tiles don't have to be initialized for commit.
2013 layer_->SetPosition(gfx::Point(100, 100));
2014 layer_tree_host()->SetViewportSize(bounds_);
2015 layer_tree_host()->SetRootLayer(layer_);
2017 PostSetNeedsCommitToMainThread();
2020 virtual void DidCommitAndDrawFrame() OVERRIDE {
2021 picture_ = layer_tree_host()->CapturePicture();
2022 EndTest();
2025 virtual void AfterTest() OVERRIDE {
2026 EXPECT_EQ(bounds_, gfx::Size(picture_->width(), picture_->height()));
2028 SkBitmap bitmap;
2029 bitmap.setConfig(
2030 SkBitmap::kARGB_8888_Config, bounds_.width(), bounds_.height());
2031 bitmap.allocPixels();
2032 bitmap.eraseARGB(0, 0, 0, 0);
2033 SkCanvas canvas(bitmap);
2035 picture_->draw(&canvas);
2037 bitmap.lockPixels();
2038 SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
2039 EXPECT_EQ(SK_ColorGREEN, pixels[0]);
2040 bitmap.unlockPixels();
2043 private:
2044 gfx::Size bounds_;
2045 FillRectContentLayerClient content_client_;
2046 scoped_refptr<PictureLayer> layer_;
2047 skia::RefPtr<SkPicture> picture_;
2050 MULTI_THREAD_TEST_F(LayerTreeHostTestCapturePicture);
2052 class LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted
2053 : public LayerTreeHostTest {
2054 public:
2055 LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted()
2056 : root_layer_(FakeContentLayer::Create(&client_)),
2057 child_layer1_(FakeContentLayer::Create(&client_)),
2058 child_layer2_(FakeContentLayer::Create(&client_)),
2059 num_commits_(0) {}
2061 virtual void BeginTest() OVERRIDE {
2062 layer_tree_host()->SetViewportSize(gfx::Size(100, 100));
2063 root_layer_->SetBounds(gfx::Size(100, 100));
2064 child_layer1_->SetBounds(gfx::Size(100, 100));
2065 child_layer2_->SetBounds(gfx::Size(100, 100));
2066 root_layer_->AddChild(child_layer1_);
2067 root_layer_->AddChild(child_layer2_);
2068 layer_tree_host()->SetRootLayer(root_layer_);
2069 PostSetNeedsCommitToMainThread();
2072 virtual void DidSetVisibleOnImplTree(LayerTreeHostImpl* host_impl,
2073 bool visible) OVERRIDE {
2074 // One backing should remain unevicted.
2075 EXPECT_EQ(100u * 100u * 4u * 1u,
2076 layer_tree_host()->contents_texture_manager()->MemoryUseBytes());
2077 // Make sure that contents textures are marked as having been
2078 // purged.
2079 EXPECT_TRUE(host_impl->active_tree()->ContentsTexturesPurged());
2080 // End the test in this state.
2081 EndTest();
2084 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2085 ++num_commits_;
2086 switch (num_commits_) {
2087 case 1:
2088 // All three backings should have memory.
2089 EXPECT_EQ(
2090 100u * 100u * 4u * 3u,
2091 layer_tree_host()->contents_texture_manager()->MemoryUseBytes());
2092 // Set a new policy that will kick out 1 of the 3 resources.
2093 // Because a resource was evicted, a commit will be kicked off.
2094 host_impl->SetManagedMemoryPolicy(
2095 ManagedMemoryPolicy(100 * 100 * 4 * 2,
2096 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING,
2097 100 * 100 * 4 * 1,
2098 ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING));
2099 break;
2100 case 2:
2101 // Only two backings should have memory.
2102 EXPECT_EQ(
2103 100u * 100u * 4u * 2u,
2104 layer_tree_host()->contents_texture_manager()->MemoryUseBytes());
2105 // Become backgrounded, which will cause 1 more resource to be
2106 // evicted.
2107 PostSetVisibleToMainThread(false);
2108 break;
2109 default:
2110 // No further commits should happen because this is not visible
2111 // anymore.
2112 NOTREACHED();
2113 break;
2117 virtual void AfterTest() OVERRIDE {}
2119 private:
2120 FakeContentLayerClient client_;
2121 scoped_refptr<FakeContentLayer> root_layer_;
2122 scoped_refptr<FakeContentLayer> child_layer1_;
2123 scoped_refptr<FakeContentLayer> child_layer2_;
2124 int num_commits_;
2127 SINGLE_AND_MULTI_THREAD_TEST_F(
2128 LayerTreeHostTestShutdownWithOnlySomeResourcesEvicted);
2130 class LayerTreeHostTestLCDNotification : public LayerTreeHostTest {
2131 public:
2132 class NotificationClient : public ContentLayerClient {
2133 public:
2134 NotificationClient()
2135 : layer_(0), paint_count_(0), lcd_notification_count_(0) {}
2137 void set_layer(Layer* layer) { layer_ = layer; }
2138 int paint_count() const { return paint_count_; }
2139 int lcd_notification_count() const { return lcd_notification_count_; }
2141 virtual void PaintContents(SkCanvas* canvas,
2142 gfx::Rect clip,
2143 gfx::RectF* opaque) OVERRIDE {
2144 ++paint_count_;
2146 virtual void DidChangeLayerCanUseLCDText() OVERRIDE {
2147 ++lcd_notification_count_;
2148 layer_->SetNeedsDisplay();
2151 private:
2152 Layer* layer_;
2153 int paint_count_;
2154 int lcd_notification_count_;
2157 virtual void SetupTree() OVERRIDE {
2158 scoped_refptr<ContentLayer> root_layer = ContentLayer::Create(&client_);
2159 root_layer->SetIsDrawable(true);
2160 root_layer->SetBounds(gfx::Size(1, 1));
2162 layer_tree_host()->SetRootLayer(root_layer);
2163 client_.set_layer(root_layer.get());
2165 // The expecations are based on the assumption that the default
2166 // LCD settings are:
2167 EXPECT_TRUE(layer_tree_host()->settings().can_use_lcd_text);
2168 EXPECT_FALSE(root_layer->can_use_lcd_text());
2170 LayerTreeHostTest::SetupTree();
2173 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
2174 virtual void AfterTest() OVERRIDE {}
2176 virtual void DidCommit() OVERRIDE {
2177 switch (layer_tree_host()->commit_number()) {
2178 case 1:
2179 // The first update consists one LCD notification and one paint.
2180 EXPECT_EQ(1, client_.lcd_notification_count());
2181 EXPECT_EQ(1, client_.paint_count());
2182 // LCD text must have been enabled on the layer.
2183 EXPECT_TRUE(layer_tree_host()->root_layer()->can_use_lcd_text());
2184 PostSetNeedsCommitToMainThread();
2185 break;
2186 case 2:
2187 // Since nothing changed on layer, there should be no notification
2188 // or paint on the second update.
2189 EXPECT_EQ(1, client_.lcd_notification_count());
2190 EXPECT_EQ(1, client_.paint_count());
2191 // LCD text must not have changed.
2192 EXPECT_TRUE(layer_tree_host()->root_layer()->can_use_lcd_text());
2193 // Change layer opacity that should trigger lcd notification.
2194 layer_tree_host()->root_layer()->SetOpacity(.5f);
2195 // No need to request a commit - setting opacity will do it.
2196 break;
2197 default:
2198 // Verify that there is not extra commit due to layer invalidation.
2199 EXPECT_EQ(3, layer_tree_host()->commit_number());
2200 // LCD notification count should have incremented due to
2201 // change in layer opacity.
2202 EXPECT_EQ(2, client_.lcd_notification_count());
2203 // Paint count should be incremented due to invalidation.
2204 EXPECT_EQ(2, client_.paint_count());
2205 // LCD text must have been disabled on the layer due to opacity.
2206 EXPECT_FALSE(layer_tree_host()->root_layer()->can_use_lcd_text());
2207 EndTest();
2208 break;
2212 private:
2213 NotificationClient client_;
2216 SINGLE_THREAD_TEST_F(LayerTreeHostTestLCDNotification);
2218 // Verify that the BeginFrame notification is used to initiate rendering.
2219 class LayerTreeHostTestBeginFrameNotification : public LayerTreeHostTest {
2220 public:
2221 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
2222 settings->begin_frame_scheduling_enabled = true;
2225 virtual void BeginTest() OVERRIDE {
2226 // This will trigger a SetNeedsBeginFrame which will trigger a BeginFrame.
2227 PostSetNeedsCommitToMainThread();
2230 virtual bool PrepareToDrawOnThread(
2231 LayerTreeHostImpl* host_impl,
2232 LayerTreeHostImpl::FrameData* frame,
2233 bool result) OVERRIDE {
2234 EndTest();
2235 return true;
2238 virtual void AfterTest() OVERRIDE {}
2240 private:
2241 base::TimeTicks frame_time_;
2244 MULTI_THREAD_TEST_F(LayerTreeHostTestBeginFrameNotification);
2246 class LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled
2247 : public LayerTreeHostTest {
2248 public:
2249 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
2250 settings->begin_frame_scheduling_enabled = true;
2251 settings->using_synchronous_renderer_compositor = true;
2254 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
2256 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2257 // The BeginFrame notification is turned off now but will get enabled
2258 // once we return. End test while it's enabled.
2259 ImplThreadTaskRunner()->PostTask(
2260 FROM_HERE,
2261 base::Bind(&LayerTreeHostTestBeginFrameNotification::EndTest,
2262 base::Unretained(this)));
2265 virtual void AfterTest() OVERRIDE {}
2268 MULTI_THREAD_TEST_F(
2269 LayerTreeHostTestBeginFrameNotificationShutdownWhileEnabled);
2271 class LayerTreeHostTestUninvertibleTransformDoesNotBlockActivation
2272 : public LayerTreeHostTest {
2273 protected:
2274 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
2275 settings->impl_side_painting = true;
2278 virtual void SetupTree() OVERRIDE {
2279 LayerTreeHostTest::SetupTree();
2281 scoped_refptr<Layer> layer = PictureLayer::Create(&client_);
2282 layer->SetTransform(gfx::Transform(0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
2283 layer->SetBounds(gfx::Size(10, 10));
2284 layer_tree_host()->root_layer()->AddChild(layer);
2287 virtual void BeginTest() OVERRIDE {
2288 PostSetNeedsCommitToMainThread();
2291 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2292 EndTest();
2295 virtual void AfterTest() OVERRIDE {
2298 FakeContentLayerClient client_;
2301 MULTI_THREAD_TEST_F(
2302 LayerTreeHostTestUninvertibleTransformDoesNotBlockActivation);
2304 class LayerTreeHostTestChangeLayerPropertiesInPaintContents
2305 : public LayerTreeHostTest {
2306 public:
2307 class SetBoundsClient : public ContentLayerClient {
2308 public:
2309 SetBoundsClient() : layer_(0) {}
2311 void set_layer(Layer* layer) { layer_ = layer; }
2313 virtual void PaintContents(SkCanvas* canvas,
2314 gfx::Rect clip,
2315 gfx::RectF* opaque) OVERRIDE {
2316 layer_->SetBounds(gfx::Size(2, 2));
2319 virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
2321 private:
2322 Layer* layer_;
2325 LayerTreeHostTestChangeLayerPropertiesInPaintContents() : num_commits_(0) {}
2327 virtual void SetupTree() OVERRIDE {
2328 scoped_refptr<ContentLayer> root_layer = ContentLayer::Create(&client_);
2329 root_layer->SetIsDrawable(true);
2330 root_layer->SetBounds(gfx::Size(1, 1));
2332 layer_tree_host()->SetRootLayer(root_layer);
2333 client_.set_layer(root_layer.get());
2335 LayerTreeHostTest::SetupTree();
2338 virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
2339 virtual void AfterTest() OVERRIDE {}
2341 virtual void CommitCompleteOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2342 num_commits_++;
2343 if (num_commits_ == 1) {
2344 LayerImpl* root_layer = host_impl->active_tree()->root_layer();
2345 EXPECT_SIZE_EQ(gfx::Size(1, 1), root_layer->bounds());
2346 } else {
2347 LayerImpl* root_layer = host_impl->active_tree()->root_layer();
2348 EXPECT_SIZE_EQ(gfx::Size(2, 2), root_layer->bounds());
2349 EndTest();
2353 private:
2354 SetBoundsClient client_;
2355 int num_commits_;
2358 SINGLE_THREAD_TEST_F(LayerTreeHostTestChangeLayerPropertiesInPaintContents);
2360 class MockIOSurfaceWebGraphicsContext3D : public FakeWebGraphicsContext3D {
2361 public:
2362 MockIOSurfaceWebGraphicsContext3D()
2363 : FakeWebGraphicsContext3D() {}
2365 virtual WebKit::WebGLId createTexture() OVERRIDE {
2366 return 1;
2369 virtual WebKit::WebString getString(WebKit::WGC3Denum name) OVERRIDE {
2370 if (name == GL_EXTENSIONS) {
2371 return WebKit::WebString(
2372 "GL_CHROMIUM_iosurface GL_ARB_texture_rectangle");
2374 return WebKit::WebString();
2377 MOCK_METHOD1(activeTexture, void(WebKit::WGC3Denum texture));
2378 MOCK_METHOD2(bindTexture, void(WebKit::WGC3Denum target,
2379 WebKit::WebGLId texture_id));
2380 MOCK_METHOD3(texParameteri, void(WebKit::WGC3Denum target,
2381 WebKit::WGC3Denum pname,
2382 WebKit::WGC3Dint param));
2383 MOCK_METHOD5(texImageIOSurface2DCHROMIUM, void(WebKit::WGC3Denum target,
2384 WebKit::WGC3Dint width,
2385 WebKit::WGC3Dint height,
2386 WebKit::WGC3Duint ioSurfaceId,
2387 WebKit::WGC3Duint plane));
2388 MOCK_METHOD4(drawElements, void(WebKit::WGC3Denum mode,
2389 WebKit::WGC3Dsizei count,
2390 WebKit::WGC3Denum type,
2391 WebKit::WGC3Dintptr offset));
2395 class LayerTreeHostTestIOSurfaceDrawing : public LayerTreeHostTest {
2396 protected:
2397 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
2398 scoped_ptr<MockIOSurfaceWebGraphicsContext3D> context(
2399 new MockIOSurfaceWebGraphicsContext3D);
2400 mock_context_ = context.get();
2401 scoped_ptr<OutputSurface> output_surface = FakeOutputSurface::Create3d(
2402 context.PassAs<WebKit::WebGraphicsContext3D>()).PassAs<OutputSurface>();
2403 return output_surface.Pass();
2406 virtual void SetupTree() OVERRIDE {
2407 LayerTreeHostTest::SetupTree();
2409 layer_tree_host()->root_layer()->SetIsDrawable(false);
2411 io_surface_id_ = 9;
2412 io_surface_size_ = gfx::Size(6, 7);
2414 scoped_refptr<IOSurfaceLayer> io_surface_layer = IOSurfaceLayer::Create();
2415 io_surface_layer->SetBounds(gfx::Size(10, 10));
2416 io_surface_layer->SetAnchorPoint(gfx::PointF());
2417 io_surface_layer->SetIsDrawable(true);
2418 io_surface_layer->SetIOSurfaceProperties(io_surface_id_, io_surface_size_);
2419 layer_tree_host()->root_layer()->AddChild(io_surface_layer);
2422 virtual void BeginTest() OVERRIDE {
2423 PostSetNeedsCommitToMainThread();
2426 virtual void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2427 // In WillDraw, the IOSurfaceLayer sets up the io surface texture.
2429 EXPECT_CALL(*mock_context_, activeTexture(_))
2430 .Times(0);
2431 EXPECT_CALL(*mock_context_, bindTexture(GL_TEXTURE_RECTANGLE_ARB, 1))
2432 .Times(AtLeast(1));
2433 EXPECT_CALL(*mock_context_, texParameteri(GL_TEXTURE_RECTANGLE_ARB,
2434 GL_TEXTURE_MIN_FILTER,
2435 GL_LINEAR))
2436 .Times(1);
2437 EXPECT_CALL(*mock_context_, texParameteri(GL_TEXTURE_RECTANGLE_ARB,
2438 GL_TEXTURE_MAG_FILTER,
2439 GL_LINEAR))
2440 .Times(1);
2441 EXPECT_CALL(*mock_context_, texParameteri(GL_TEXTURE_RECTANGLE_ARB,
2442 GL_TEXTURE_WRAP_S,
2443 GL_CLAMP_TO_EDGE))
2444 .Times(1);
2445 EXPECT_CALL(*mock_context_, texParameteri(GL_TEXTURE_RECTANGLE_ARB,
2446 GL_TEXTURE_WRAP_T,
2447 GL_CLAMP_TO_EDGE))
2448 .Times(1);
2450 EXPECT_CALL(*mock_context_, texImageIOSurface2DCHROMIUM(
2451 GL_TEXTURE_RECTANGLE_ARB,
2452 io_surface_size_.width(),
2453 io_surface_size_.height(),
2454 io_surface_id_,
2456 .Times(1);
2458 EXPECT_CALL(*mock_context_, bindTexture(_, 0))
2459 .Times(AnyNumber());
2462 virtual bool PrepareToDrawOnThread(
2463 LayerTreeHostImpl* host_impl,
2464 LayerTreeHostImpl::FrameData* frame,
2465 bool result) OVERRIDE {
2466 Mock::VerifyAndClearExpectations(&mock_context_);
2468 // The io surface layer's texture is drawn.
2469 EXPECT_CALL(*mock_context_, activeTexture(GL_TEXTURE0))
2470 .Times(AtLeast(1));
2471 EXPECT_CALL(*mock_context_, bindTexture(GL_TEXTURE_RECTANGLE_ARB, 1))
2472 .Times(1);
2473 EXPECT_CALL(*mock_context_, drawElements(GL_TRIANGLES, 6, _, _))
2474 .Times(AtLeast(1));
2476 return result;
2479 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2480 Mock::VerifyAndClearExpectations(&mock_context_);
2481 EndTest();
2484 virtual void AfterTest() OVERRIDE {}
2486 int io_surface_id_;
2487 MockIOSurfaceWebGraphicsContext3D* mock_context_;
2488 gfx::Size io_surface_size_;
2491 // TODO(danakj): IOSurface layer can not be transported. crbug.com/239335
2492 SINGLE_AND_MULTI_THREAD_DIRECT_RENDERER_TEST_F(
2493 LayerTreeHostTestIOSurfaceDrawing);
2495 class LayerTreeHostTestAsyncReadback : public LayerTreeHostTest {
2496 protected:
2497 virtual void SetupTree() OVERRIDE {
2498 root = FakeContentLayer::Create(&client_);
2499 root->SetBounds(gfx::Size(20, 20));
2501 child = FakeContentLayer::Create(&client_);
2502 child->SetBounds(gfx::Size(10, 10));
2503 root->AddChild(child);
2505 layer_tree_host()->SetRootLayer(root);
2506 LayerTreeHostTest::SetupTree();
2509 virtual void BeginTest() OVERRIDE {
2510 PostSetNeedsCommitToMainThread();
2513 virtual void DidCommitAndDrawFrame() OVERRIDE {
2514 WaitForCallback();
2517 void WaitForCallback() {
2518 base::MessageLoop::current()->PostTask(
2519 FROM_HERE,
2520 base::Bind(
2521 &LayerTreeHostTestAsyncReadback::NextStep,
2522 base::Unretained(this)));
2525 void NextStep() {
2526 int frame = layer_tree_host()->commit_number();
2527 switch (frame) {
2528 case 1:
2529 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
2530 base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
2531 base::Unretained(this))));
2532 EXPECT_EQ(0u, callbacks_.size());
2533 break;
2534 case 2:
2535 if (callbacks_.size() < 1u) {
2536 WaitForCallback();
2537 return;
2539 EXPECT_EQ(1u, callbacks_.size());
2540 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[0].ToString());
2542 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
2543 base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
2544 base::Unretained(this))));
2545 root->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
2546 base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
2547 base::Unretained(this))));
2548 child->RequestCopyOfOutput(CopyOutputRequest::CreateBitmapRequest(
2549 base::Bind(&LayerTreeHostTestAsyncReadback::CopyOutputCallback,
2550 base::Unretained(this))));
2551 EXPECT_EQ(1u, callbacks_.size());
2552 break;
2553 case 3:
2554 if (callbacks_.size() < 4u) {
2555 WaitForCallback();
2556 return;
2558 EXPECT_EQ(4u, callbacks_.size());
2559 // The child was copied to a bitmap and passed back twice.
2560 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[1].ToString());
2561 EXPECT_EQ(gfx::Size(10, 10).ToString(), callbacks_[2].ToString());
2562 // The root was copied to a bitmap and passed back also.
2563 EXPECT_EQ(gfx::Size(20, 20).ToString(), callbacks_[3].ToString());
2564 EndTest();
2565 break;
2569 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
2570 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
2571 EXPECT_TRUE(result->HasBitmap());
2572 scoped_ptr<SkBitmap> bitmap = result->TakeBitmap().Pass();
2573 EXPECT_EQ(result->size().ToString(),
2574 gfx::Size(bitmap->width(), bitmap->height()).ToString());
2575 callbacks_.push_back(result->size());
2578 virtual void AfterTest() OVERRIDE {
2579 EXPECT_EQ(4u, callbacks_.size());
2582 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
2583 if (use_gl_renderer_)
2584 return FakeOutputSurface::Create3d().PassAs<OutputSurface>();
2585 return FakeOutputSurface::CreateSoftware(
2586 make_scoped_ptr(new SoftwareOutputDevice)).PassAs<OutputSurface>();
2589 bool use_gl_renderer_;
2590 std::vector<gfx::Size> callbacks_;
2591 FakeContentLayerClient client_;
2592 scoped_refptr<FakeContentLayer> root;
2593 scoped_refptr<FakeContentLayer> child;
2596 // Readback can't be done with a delegating renderer.
2597 TEST_F(LayerTreeHostTestAsyncReadback, GLRenderer_RunSingleThread) {
2598 use_gl_renderer_ = true;
2599 RunTest(false, false, false);
2602 TEST_F(LayerTreeHostTestAsyncReadback,
2603 GLRenderer_RunMultiThread_MainThreadPainting) {
2604 use_gl_renderer_ = true;
2605 RunTest(true, false, false);
2608 TEST_F(LayerTreeHostTestAsyncReadback,
2609 GLRenderer_RunMultiThread_ImplSidePainting) {
2610 use_gl_renderer_ = true;
2611 RunTest(true, false, true);
2614 TEST_F(LayerTreeHostTestAsyncReadback, SoftwareRenderer_RunSingleThread) {
2615 use_gl_renderer_ = false;
2616 RunTest(false, false, false);
2619 TEST_F(LayerTreeHostTestAsyncReadback,
2620 SoftwareRenderer_RunMultiThread_MainThreadPainting) {
2621 use_gl_renderer_ = false;
2622 RunTest(true, false, false);
2625 TEST_F(LayerTreeHostTestAsyncReadback,
2626 SoftwareRenderer_RunMultiThread_ImplSidePainting) {
2627 use_gl_renderer_ = false;
2628 RunTest(true, false, true);
2631 class LayerTreeHostTestAsyncReadbackLayerDestroyed : public LayerTreeHostTest {
2632 protected:
2633 virtual void SetupTree() OVERRIDE {
2634 root_ = FakeContentLayer::Create(&client_);
2635 root_->SetBounds(gfx::Size(20, 20));
2637 main_destroyed_ = FakeContentLayer::Create(&client_);
2638 main_destroyed_->SetBounds(gfx::Size(15, 15));
2639 root_->AddChild(main_destroyed_);
2641 impl_destroyed_ = FakeContentLayer::Create(&client_);
2642 impl_destroyed_->SetBounds(gfx::Size(10, 10));
2643 root_->AddChild(impl_destroyed_);
2645 layer_tree_host()->SetRootLayer(root_);
2646 LayerTreeHostTest::SetupTree();
2649 virtual void BeginTest() OVERRIDE {
2650 callback_count_ = 0;
2651 PostSetNeedsCommitToMainThread();
2654 virtual void DidCommit() OVERRIDE {
2655 int frame = layer_tree_host()->commit_number();
2656 switch (frame) {
2657 case 1:
2658 main_destroyed_->RequestCopyOfOutput(
2659 CopyOutputRequest::CreateBitmapRequest(base::Bind(
2660 &LayerTreeHostTestAsyncReadbackLayerDestroyed::
2661 CopyOutputCallback,
2662 base::Unretained(this))));
2663 impl_destroyed_->RequestCopyOfOutput(
2664 CopyOutputRequest::CreateBitmapRequest(base::Bind(
2665 &LayerTreeHostTestAsyncReadbackLayerDestroyed::
2666 CopyOutputCallback,
2667 base::Unretained(this))));
2668 EXPECT_EQ(0, callback_count_);
2670 // Destroy the main thread layer right away.
2671 main_destroyed_->RemoveFromParent();
2672 main_destroyed_ = NULL;
2674 // Should callback with a NULL bitmap.
2675 EXPECT_EQ(1, callback_count_);
2677 // Prevent drawing so we can't make a copy of the impl_destroyed layer.
2678 layer_tree_host()->SetViewportSize(gfx::Size());
2679 break;
2680 case 2:
2681 // Flush the message loops and make sure the callbacks run.
2682 layer_tree_host()->SetNeedsCommit();
2683 break;
2684 case 3:
2685 // No drawing means no readback yet.
2686 EXPECT_EQ(1, callback_count_);
2688 // Destroy the impl thread layer.
2689 impl_destroyed_->RemoveFromParent();
2690 impl_destroyed_ = NULL;
2692 // No callback yet because it's on the impl side.
2693 EXPECT_EQ(1, callback_count_);
2694 break;
2695 case 4:
2696 // Flush the message loops and make sure the callbacks run.
2697 layer_tree_host()->SetNeedsCommit();
2698 break;
2699 case 5:
2700 // We should get another callback with a NULL bitmap.
2701 EXPECT_EQ(2, callback_count_);
2702 EndTest();
2703 break;
2707 void CopyOutputCallback(scoped_ptr<CopyOutputResult> result) {
2708 EXPECT_TRUE(layer_tree_host()->proxy()->IsMainThread());
2709 EXPECT_TRUE(result->IsEmpty());
2710 ++callback_count_;
2713 virtual void AfterTest() OVERRIDE {}
2715 int callback_count_;
2716 FakeContentLayerClient client_;
2717 scoped_refptr<FakeContentLayer> root_;
2718 scoped_refptr<FakeContentLayer> main_destroyed_;
2719 scoped_refptr<FakeContentLayer> impl_destroyed_;
2722 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestAsyncReadbackLayerDestroyed);
2724 class LayerTreeHostTestNumFramesPending : public LayerTreeHostTest {
2725 public:
2726 virtual void BeginTest() OVERRIDE {
2727 frame_ = 0;
2728 PostSetNeedsCommitToMainThread();
2731 // Round 1: commit + draw
2732 // Round 2: commit only (no draw/swap)
2733 // Round 3: draw only (no commit)
2734 // Round 4: composite & readback (2 commits, no draw/swap)
2735 // Round 5: commit + draw
2737 virtual void DidCommit() OVERRIDE {
2738 int commit = layer_tree_host()->commit_number();
2739 switch (commit) {
2740 case 2:
2741 // Round 2 done.
2742 EXPECT_EQ(1, frame_);
2743 layer_tree_host()->SetNeedsRedraw();
2744 break;
2745 case 3:
2746 // CompositeAndReadback in Round 4, first commit.
2747 EXPECT_EQ(2, frame_);
2748 break;
2749 case 4:
2750 // Round 4 done.
2751 EXPECT_EQ(2, frame_);
2752 layer_tree_host()->SetNeedsCommit();
2753 layer_tree_host()->SetNeedsRedraw();
2754 break;
2758 virtual void DidCompleteSwapBuffers() OVERRIDE {
2759 int commit = layer_tree_host()->commit_number();
2760 ++frame_;
2761 char pixels[4] = {0};
2762 switch (frame_) {
2763 case 1:
2764 // Round 1 done.
2765 EXPECT_EQ(1, commit);
2766 layer_tree_host()->SetNeedsCommit();
2767 break;
2768 case 2:
2769 // Round 3 done.
2770 EXPECT_EQ(2, commit);
2771 layer_tree_host()->CompositeAndReadback(pixels, gfx::Rect(0, 0, 1, 1));
2772 break;
2773 case 3:
2774 // Round 5 done.
2775 EXPECT_EQ(5, commit);
2776 EndTest();
2777 break;
2781 virtual void AfterTest() OVERRIDE {}
2783 protected:
2784 int frame_;
2787 TEST_F(LayerTreeHostTestNumFramesPending, DelegatingRenderer) {
2788 RunTest(true, true, true);
2791 TEST_F(LayerTreeHostTestNumFramesPending, GLRenderer) {
2792 RunTest(true, false, true);
2795 class LayerTreeHostTestDeferredInitialize : public LayerTreeHostTest {
2796 public:
2797 virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
2798 // PictureLayer can only be used with impl side painting enabled.
2799 settings->impl_side_painting = true;
2800 settings->solid_color_scrollbars = true;
2803 virtual void SetupTree() OVERRIDE {
2804 layer_ = FakePictureLayer::Create(&client_);
2805 layer_tree_host()->SetRootLayer(layer_);
2806 LayerTreeHostTest::SetupTree();
2809 virtual void BeginTest() OVERRIDE {
2810 initialized_gl_ = false;
2811 PostSetNeedsCommitToMainThread();
2814 virtual scoped_ptr<OutputSurface> CreateOutputSurface() OVERRIDE {
2815 scoped_ptr<TestWebGraphicsContext3D> context3d(
2816 TestWebGraphicsContext3D::Create());
2817 context3d->set_support_swapbuffers_complete_callback(false);
2819 return FakeOutputSurface::CreateDeferredGL(
2820 scoped_ptr<SoftwareOutputDevice>(new SoftwareOutputDevice))
2821 .PassAs<OutputSurface>();
2824 virtual void DrawLayersOnThread(LayerTreeHostImpl* host_impl) OVERRIDE {
2825 ASSERT_TRUE(host_impl->RootLayer());
2826 FakePictureLayerImpl* layer_impl =
2827 static_cast<FakePictureLayerImpl*>(host_impl->RootLayer());
2828 if (!initialized_gl_) {
2829 EXPECT_EQ(1u, layer_impl->append_quads_count());
2830 ImplThreadTaskRunner()->PostTask(FROM_HERE, base::Bind(
2831 &LayerTreeHostTestDeferredInitialize::DeferredInitializeAndRedraw,
2832 base::Unretained(this),
2833 base::Unretained(host_impl)));
2834 } else {
2835 EXPECT_EQ(2u, layer_impl->append_quads_count());
2836 EndTest();
2840 void DeferredInitializeAndRedraw(LayerTreeHostImpl* host_impl) {
2841 EXPECT_TRUE(static_cast<FakeOutputSurface*>(host_impl->output_surface())
2842 ->SetAndInitializeContext3D(
2843 scoped_ptr<WebKit::WebGraphicsContext3D>(
2844 TestWebGraphicsContext3D::Create())));
2845 initialized_gl_ = true;
2847 // Force redraw again.
2848 host_impl->SetNeedsRedrawRect(gfx::Rect(1, 1));
2850 // If we didn't swap this begin frame, we need to request another one.
2851 host_impl->SetNeedsBeginFrame(true);
2854 virtual void AfterTest() OVERRIDE {
2855 EXPECT_TRUE(initialized_gl_);
2858 private:
2859 FakeContentLayerClient client_;
2860 scoped_refptr<FakePictureLayer> layer_;
2861 bool initialized_gl_;
2864 MULTI_THREAD_TEST_F(LayerTreeHostTestDeferredInitialize);
2866 } // namespace
2867 } // namespace cc