WebKit Roll 139512:139548
[chromium-blink-merge.git] / cc / layer_tree_host_unittest.cc
blob703217dd07df7842c470df7a83aa0e44cb7fe8d2
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/layer_tree_host.h"
7 #include "base/synchronization/lock.h"
8 #include "cc/content_layer.h"
9 #include "cc/content_layer_client.h"
10 #include "cc/layer_impl.h"
11 #include "cc/layer_tree_host_impl.h"
12 #include "cc/layer_tree_impl.h"
13 #include "cc/output_surface.h"
14 #include "cc/picture_layer.h"
15 #include "cc/prioritized_resource.h"
16 #include "cc/single_thread_proxy.h"
17 #include "cc/test/fake_content_layer.h"
18 #include "cc/test/fake_content_layer_client.h"
19 #include "cc/test/fake_layer_tree_host_client.h"
20 #include "cc/test/fake_output_surface.h"
21 #include "cc/test/fake_proxy.h"
22 #include "cc/test/fake_scrollbar_layer.h"
23 #include "cc/test/geometry_test_utils.h"
24 #include "cc/test/layer_tree_test_common.h"
25 #include "cc/resource_update_queue.h"
26 #include "cc/test/occlusion_tracker_test_common.h"
27 #include "cc/timing_function.h"
28 #include "skia/ext/refptr.h"
29 #include "testing/gmock/include/gmock/gmock.h"
30 #include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
31 #include "third_party/khronos/GLES2/gl2.h"
32 #include "third_party/khronos/GLES2/gl2ext.h"
33 #include "third_party/skia/include/core/SkPicture.h"
34 #include "ui/gfx/point_conversions.h"
35 #include "ui/gfx/size_conversions.h"
36 #include "ui/gfx/vector2d_conversions.h"
38 namespace cc {
39 namespace {
41 class LayerTreeHostTest : public ThreadedTest { };
43 // Shortlived layerTreeHosts shouldn't die.
44 class LayerTreeHostTestShortlived1 : public LayerTreeHostTest {
45 public:
46 LayerTreeHostTestShortlived1() { }
48 virtual void beginTest() OVERRIDE
50 // Kill the layerTreeHost immediately.
51 m_layerTreeHost->setRootLayer(0);
52 m_layerTreeHost.reset();
54 endTest();
57 virtual void afterTest() OVERRIDE
62 // Shortlived layerTreeHosts shouldn't die with a commit in flight.
63 class LayerTreeHostTestShortlived2 : public LayerTreeHostTest {
64 public:
65 LayerTreeHostTestShortlived2() { }
67 virtual void beginTest() OVERRIDE
69 postSetNeedsCommitToMainThread();
71 // Kill the layerTreeHost immediately.
72 m_layerTreeHost->setRootLayer(0);
73 m_layerTreeHost.reset();
75 endTest();
78 virtual void afterTest() OVERRIDE
83 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestShortlived2)
85 // Shortlived layerTreeHosts shouldn't die with a redraw in flight.
86 class LayerTreeHostTestShortlived3 : public LayerTreeHostTest {
87 public:
88 LayerTreeHostTestShortlived3() { }
90 virtual void beginTest() OVERRIDE
92 postSetNeedsRedrawToMainThread();
94 // Kill the layerTreeHost immediately.
95 m_layerTreeHost->setRootLayer(0);
96 m_layerTreeHost.reset();
98 endTest();
101 virtual void afterTest() OVERRIDE
106 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestShortlived3)
108 // Test interleaving of redraws and commits
109 class LayerTreeHostTestCommitingWithContinuousRedraw : public LayerTreeHostTest {
110 public:
111 LayerTreeHostTestCommitingWithContinuousRedraw()
112 : m_numCompleteCommits(0)
113 , m_numDraws(0)
117 virtual void beginTest() OVERRIDE
119 postSetNeedsCommitToMainThread();
122 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
124 m_numCompleteCommits++;
125 if (m_numCompleteCommits == 2)
126 endTest();
129 virtual void drawLayersOnThread(LayerTreeHostImpl*) OVERRIDE
131 if (m_numDraws == 1)
132 postSetNeedsCommitToMainThread();
133 m_numDraws++;
134 postSetNeedsRedrawToMainThread();
137 virtual void afterTest() OVERRIDE
141 private:
142 int m_numCompleteCommits;
143 int m_numDraws;
146 TEST_F(LayerTreeHostTestCommitingWithContinuousRedraw, runMultiThread)
148 runTest(true);
151 // Two setNeedsCommits in a row should lead to at least 1 commit and at least 1
152 // draw with frame 0.
153 class LayerTreeHostTestSetNeedsCommit1 : public LayerTreeHostTest {
154 public:
155 LayerTreeHostTestSetNeedsCommit1()
156 : m_numCommits(0)
157 , m_numDraws(0)
161 virtual void beginTest() OVERRIDE
163 postSetNeedsCommitToMainThread();
164 postSetNeedsCommitToMainThread();
167 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
169 m_numDraws++;
170 if (!impl->activeTree()->source_frame_number())
171 endTest();
174 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
176 m_numCommits++;
179 virtual void afterTest() OVERRIDE
181 EXPECT_GE(1, m_numCommits);
182 EXPECT_GE(1, m_numDraws);
185 private:
186 int m_numCommits;
187 int m_numDraws;
190 TEST_F(LayerTreeHostTestSetNeedsCommit1, DISABLED_runMultiThread)
192 runTest(true);
195 // A setNeedsCommit should lead to 1 commit. Issuing a second commit after that
196 // first committed frame draws should lead to another commit.
197 class LayerTreeHostTestSetNeedsCommit2 : public LayerTreeHostTest {
198 public:
199 LayerTreeHostTestSetNeedsCommit2()
200 : m_numCommits(0)
201 , m_numDraws(0)
205 virtual void beginTest() OVERRIDE
207 postSetNeedsCommitToMainThread();
210 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
212 if (impl->activeTree()->source_frame_number() == 0)
213 postSetNeedsCommitToMainThread();
214 else if (impl->activeTree()->source_frame_number() == 1)
215 endTest();
218 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
220 m_numCommits++;
223 virtual void afterTest() OVERRIDE
225 EXPECT_EQ(2, m_numCommits);
226 EXPECT_GE(2, m_numDraws);
229 private:
230 int m_numCommits;
231 int m_numDraws;
234 TEST_F(LayerTreeHostTestSetNeedsCommit2, runMultiThread)
236 runTest(true);
239 // 1 setNeedsRedraw after the first commit has completed should lead to 1
240 // additional draw.
241 class LayerTreeHostTestSetNeedsRedraw : public LayerTreeHostTest {
242 public:
243 LayerTreeHostTestSetNeedsRedraw()
244 : m_numCommits(0)
245 , m_numDraws(0)
249 virtual void beginTest() OVERRIDE
251 postSetNeedsCommitToMainThread();
254 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
256 EXPECT_EQ(0, impl->activeTree()->source_frame_number());
257 if (!m_numDraws)
258 postSetNeedsRedrawToMainThread(); // Redraw again to verify that the second redraw doesn't commit.
259 else
260 endTest();
261 m_numDraws++;
264 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
266 EXPECT_EQ(0, m_numDraws);
267 m_numCommits++;
270 virtual void afterTest() OVERRIDE
272 EXPECT_GE(2, m_numDraws);
273 EXPECT_EQ(1, m_numCommits);
276 private:
277 int m_numCommits;
278 int m_numDraws;
281 TEST_F(LayerTreeHostTestSetNeedsRedraw, runMultiThread)
283 runTest(true);
286 class LayerTreeHostTestNoExtraCommitFromInvalidate : public LayerTreeHostTest {
287 public:
288 LayerTreeHostTestNoExtraCommitFromInvalidate()
289 : m_rootLayer(ContentLayer::create(&m_client))
293 virtual void beginTest() OVERRIDE
295 m_rootLayer->setAutomaticallyComputeRasterScale(false);
296 m_rootLayer->setIsDrawable(true);
297 m_rootLayer->setBounds(gfx::Size(1, 1));
298 m_layerTreeHost->setRootLayer(m_rootLayer);
299 postSetNeedsCommitToMainThread();
302 virtual void didCommit() OVERRIDE
304 switch (m_layerTreeHost->commitNumber()) {
305 case 1:
306 // Changing the content bounds will cause a single commit!
307 m_rootLayer->setRasterScale(4.0f);
308 break;
309 default:
310 // No extra commits.
311 EXPECT_EQ(2, m_layerTreeHost->commitNumber());
312 endTest();
316 virtual void afterTest() OVERRIDE
320 private:
321 FakeContentLayerClient m_client;
322 scoped_refptr<ContentLayer> m_rootLayer;
325 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestNoExtraCommitFromInvalidate)
327 class LayerTreeHostTestCompositeAndReadback : public LayerTreeHostTest {
328 public:
329 LayerTreeHostTestCompositeAndReadback()
330 : m_numCommits(0)
334 virtual void beginTest() OVERRIDE
336 postSetNeedsCommitToMainThread();
339 virtual void didCommit() OVERRIDE
341 m_numCommits++;
342 if (m_numCommits == 1) {
343 char pixels[4];
344 m_layerTreeHost->compositeAndReadback(static_cast<void*>(&pixels), gfx::Rect(0, 0, 1, 1));
345 } else if (m_numCommits == 2) {
346 // This is inside the readback. We should get another commit after it.
347 } else if (m_numCommits == 3) {
348 endTest();
349 } else {
350 NOTREACHED();
354 virtual void afterTest() OVERRIDE
358 private:
359 int m_numCommits;
362 TEST_F(LayerTreeHostTestCompositeAndReadback, runMultiThread)
364 runTest(true);
367 class LayerTreeHostTestCompositeAndReadbackBeforePreviousCommitDraws : public LayerTreeHostTest {
368 public:
369 LayerTreeHostTestCompositeAndReadbackBeforePreviousCommitDraws()
370 : m_numCommits(0)
374 virtual void beginTest() OVERRIDE
376 postSetNeedsCommitToMainThread();
379 virtual void didCommit() OVERRIDE
381 m_numCommits++;
382 if (m_numCommits == 1) {
383 m_layerTreeHost->setNeedsCommit();
384 } else if (m_numCommits == 2) {
385 char pixels[4];
386 m_layerTreeHost->compositeAndReadback(static_cast<void*>(&pixels), gfx::Rect(0, 0, 1, 1));
387 } else if (m_numCommits == 3) {
388 // This is inside the readback. We should get another commit after it.
389 } else if (m_numCommits == 4) {
390 endTest();
391 } else {
392 NOTREACHED();
396 virtual void afterTest() OVERRIDE
400 private:
401 int m_numCommits;
404 TEST_F(LayerTreeHostTestCompositeAndReadbackBeforePreviousCommitDraws, runMultiThread)
406 runTest(true);
409 // If the layerTreeHost says it can't draw, then we should not try to draw.
410 class LayerTreeHostTestCanDrawBlocksDrawing : public LayerTreeHostTest {
411 public:
412 LayerTreeHostTestCanDrawBlocksDrawing()
413 : m_numCommits(0)
414 , m_done(false)
418 virtual void beginTest() OVERRIDE
420 postSetNeedsCommitToMainThread();
423 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
425 if (m_done)
426 return;
427 // Only the initial draw should bring us here.
428 EXPECT_TRUE(impl->canDraw());
429 EXPECT_EQ(0, impl->activeTree()->source_frame_number());
432 virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE
434 if (m_done)
435 return;
436 if (m_numCommits >= 1) {
437 // After the first commit, we should not be able to draw.
438 EXPECT_FALSE(impl->canDraw());
442 virtual void didCommit() OVERRIDE
444 m_numCommits++;
445 if (m_numCommits == 1) {
446 // Make the viewport empty so the host says it can't draw.
447 m_layerTreeHost->setViewportSize(gfx::Size(0, 0), gfx::Size(0, 0));
448 } else if (m_numCommits == 2) {
449 char pixels[4];
450 m_layerTreeHost->compositeAndReadback(&pixels, gfx::Rect(0, 0, 1, 1));
451 } else if (m_numCommits == 3) {
452 // Let it draw so we go idle and end the test.
453 m_layerTreeHost->setViewportSize(gfx::Size(1, 1), gfx::Size(1, 1));
454 m_done = true;
455 endTest();
459 virtual void afterTest() OVERRIDE
463 private:
464 int m_numCommits;
465 bool m_done;
468 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestCanDrawBlocksDrawing)
470 // beginLayerWrite should prevent draws from executing until a commit occurs
471 class LayerTreeHostTestWriteLayersRedraw : public LayerTreeHostTest {
472 public:
473 LayerTreeHostTestWriteLayersRedraw()
474 : m_numCommits(0)
475 , m_numDraws(0)
479 virtual void beginTest() OVERRIDE
481 postAcquireLayerTextures();
482 postSetNeedsRedrawToMainThread(); // should be inhibited without blocking
483 postSetNeedsCommitToMainThread();
486 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
488 m_numDraws++;
489 EXPECT_EQ(m_numDraws, m_numCommits);
492 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
494 m_numCommits++;
495 endTest();
498 virtual void afterTest() OVERRIDE
500 EXPECT_EQ(1, m_numCommits);
503 private:
504 int m_numCommits;
505 int m_numDraws;
508 TEST_F(LayerTreeHostTestWriteLayersRedraw, runMultiThread)
510 runTest(true);
513 // Verify that when resuming visibility, requesting layer write permission
514 // will not deadlock the main thread even though there are not yet any
515 // scheduled redraws. This behavior is critical for reliably surviving tab
516 // switching. There are no failure conditions to this test, it just passes
517 // by not timing out.
518 class LayerTreeHostTestWriteLayersAfterVisible : public LayerTreeHostTest {
519 public:
520 LayerTreeHostTestWriteLayersAfterVisible()
521 : m_numCommits(0)
525 virtual void beginTest() OVERRIDE
527 postSetNeedsCommitToMainThread();
530 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
532 m_numCommits++;
533 if (m_numCommits == 2)
534 endTest();
535 else if (m_numCommits < 2) {
536 postSetVisibleToMainThread(false);
537 postSetVisibleToMainThread(true);
538 postAcquireLayerTextures();
539 postSetNeedsCommitToMainThread();
543 virtual void afterTest() OVERRIDE
547 private:
548 int m_numCommits;
551 TEST_F(LayerTreeHostTestWriteLayersAfterVisible, runMultiThread)
553 runTest(true);
556 // A compositeAndReadback while invisible should force a normal commit without assertion.
557 class LayerTreeHostTestCompositeAndReadbackWhileInvisible : public LayerTreeHostTest {
558 public:
559 LayerTreeHostTestCompositeAndReadbackWhileInvisible()
560 : m_numCommits(0)
564 virtual void beginTest() OVERRIDE
566 postSetNeedsCommitToMainThread();
569 virtual void didCommitAndDrawFrame() OVERRIDE
571 m_numCommits++;
572 if (m_numCommits == 1) {
573 m_layerTreeHost->setVisible(false);
574 m_layerTreeHost->setNeedsCommit();
575 m_layerTreeHost->setNeedsCommit();
576 char pixels[4];
577 m_layerTreeHost->compositeAndReadback(static_cast<void*>(&pixels), gfx::Rect(0, 0, 1, 1));
578 } else
579 endTest();
583 virtual void afterTest() OVERRIDE
587 private:
588 int m_numCommits;
591 TEST_F(LayerTreeHostTestCompositeAndReadbackWhileInvisible, runMultiThread)
593 runTest(true);
596 class LayerTreeHostTestAbortFrameWhenInvisible : public LayerTreeHostTest {
597 public:
598 LayerTreeHostTestAbortFrameWhenInvisible()
602 virtual void beginTest() OVERRIDE
604 // Request a commit (from the main thread), which will trigger the commit flow from the impl side.
605 m_layerTreeHost->setNeedsCommit();
606 // Then mark ourselves as not visible before processing any more messages on the main thread.
607 m_layerTreeHost->setVisible(false);
608 // If we make it without kicking a frame, we pass!
609 endTestAfterDelay(1);
612 virtual void layout() OVERRIDE
614 ASSERT_FALSE(true);
615 endTest();
618 virtual void afterTest() OVERRIDE
622 private:
625 TEST_F(LayerTreeHostTestAbortFrameWhenInvisible, runMultiThread)
627 runTest(true);
630 // This test verifies that properties on the layer tree host are commited to the impl side.
631 class LayerTreeHostTestCommit : public LayerTreeHostTest {
632 public:
634 LayerTreeHostTestCommit() { }
636 virtual void beginTest() OVERRIDE
638 m_layerTreeHost->setViewportSize(gfx::Size(20, 20), gfx::Size(20, 20));
639 m_layerTreeHost->setBackgroundColor(SK_ColorGRAY);
640 m_layerTreeHost->setPageScaleFactorAndLimits(5, 5, 5);
642 postSetNeedsCommitToMainThread();
645 virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE
647 EXPECT_EQ(gfx::Size(20, 20), impl->layoutViewportSize());
648 EXPECT_EQ(SK_ColorGRAY, impl->activeTree()->background_color());
649 EXPECT_EQ(5, impl->pageScaleFactor());
651 endTest();
654 virtual void afterTest() OVERRIDE { }
657 TEST_F(LayerTreeHostTestCommit, runTest)
659 runTest(true);
662 // Verifies that startPageScaleAnimation events propagate correctly from LayerTreeHost to
663 // LayerTreeHostImpl in the MT compositor.
664 class LayerTreeHostTestStartPageScaleAnimation : public LayerTreeHostTest {
665 public:
667 LayerTreeHostTestStartPageScaleAnimation()
668 : m_animationRequested(false)
672 virtual void beginTest() OVERRIDE
674 m_layerTreeHost->rootLayer()->setScrollable(true);
675 m_layerTreeHost->rootLayer()->setScrollOffset(gfx::Vector2d());
676 postSetNeedsCommitToMainThread();
677 postSetNeedsRedrawToMainThread();
680 void requestStartPageScaleAnimation()
682 layerTreeHost()->startPageScaleAnimation(gfx::Vector2d(), false, 1.25, base::TimeDelta());
685 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
687 impl->rootLayer()->setScrollable(true);
688 impl->rootLayer()->setScrollOffset(gfx::Vector2d());
689 impl->setPageScaleFactorAndLimits(impl->pageScaleFactor(), 0.5, 2);
691 // We request animation only once.
692 if (!m_animationRequested) {
693 impl->proxy()->mainThread()->postTask(base::Bind(&LayerTreeHostTestStartPageScaleAnimation::requestStartPageScaleAnimation, base::Unretained(this)));
694 m_animationRequested = true;
698 virtual void applyScrollAndScale(gfx::Vector2d scrollDelta, float scale) OVERRIDE
700 gfx::Vector2d offset = m_layerTreeHost->rootLayer()->scrollOffset();
701 m_layerTreeHost->rootLayer()->setScrollOffset(offset + scrollDelta);
702 m_layerTreeHost->setPageScaleFactorAndLimits(scale, 0.5, 2);
705 virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE
707 impl->processScrollDeltas();
708 // We get one commit before the first draw, and the animation doesn't happen until the second draw.
709 if (impl->activeTree()->source_frame_number() == 1) {
710 EXPECT_EQ(1.25, impl->pageScaleFactor());
711 endTest();
712 } else
713 postSetNeedsRedrawToMainThread();
716 virtual void afterTest() OVERRIDE
720 private:
721 bool m_animationRequested;
724 TEST_F(LayerTreeHostTestStartPageScaleAnimation, runTest)
726 runTest(true);
729 class LayerTreeHostTestSetVisible : public LayerTreeHostTest {
730 public:
732 LayerTreeHostTestSetVisible()
733 : m_numDraws(0)
737 virtual void beginTest() OVERRIDE
739 postSetNeedsCommitToMainThread();
740 postSetVisibleToMainThread(false);
741 postSetNeedsRedrawToMainThread(); // This is suppressed while we're invisible.
742 postSetVisibleToMainThread(true); // Triggers the redraw.
745 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
747 EXPECT_TRUE(impl->visible());
748 ++m_numDraws;
749 endTest();
752 virtual void afterTest() OVERRIDE
754 EXPECT_EQ(1, m_numDraws);
757 private:
758 int m_numDraws;
761 TEST_F(LayerTreeHostTestSetVisible, runMultiThread)
763 runTest(true);
766 class TestOpacityChangeLayerDelegate : public ContentLayerClient {
767 public:
768 TestOpacityChangeLayerDelegate()
769 : m_testLayer(0)
773 void setTestLayer(Layer* testLayer)
775 m_testLayer = testLayer;
778 virtual void paintContents(SkCanvas*, const gfx::Rect&, gfx::RectF&) OVERRIDE
780 // Set layer opacity to 0.
781 if (m_testLayer)
782 m_testLayer->setOpacity(0);
785 private:
786 Layer* m_testLayer;
789 class ContentLayerWithUpdateTracking : public ContentLayer {
790 public:
791 static scoped_refptr<ContentLayerWithUpdateTracking> create(ContentLayerClient* client) { return make_scoped_refptr(new ContentLayerWithUpdateTracking(client)); }
793 int paintContentsCount() { return m_paintContentsCount; }
794 void resetPaintContentsCount() { m_paintContentsCount = 0; }
796 virtual void update(ResourceUpdateQueue& queue, const OcclusionTracker* occlusion, RenderingStats& stats) OVERRIDE
798 ContentLayer::update(queue, occlusion, stats);
799 m_paintContentsCount++;
802 private:
803 explicit ContentLayerWithUpdateTracking(ContentLayerClient* client)
804 : ContentLayer(client)
805 , m_paintContentsCount(0)
807 setAnchorPoint(gfx::PointF(0, 0));
808 setBounds(gfx::Size(10, 10));
809 setIsDrawable(true);
811 virtual ~ContentLayerWithUpdateTracking()
815 int m_paintContentsCount;
818 // Layer opacity change during paint should not prevent compositor resources from being updated during commit.
819 class LayerTreeHostTestOpacityChange : public LayerTreeHostTest {
820 public:
821 LayerTreeHostTestOpacityChange()
822 : m_testOpacityChangeDelegate()
823 , m_updateCheckLayer(ContentLayerWithUpdateTracking::create(&m_testOpacityChangeDelegate))
825 m_testOpacityChangeDelegate.setTestLayer(m_updateCheckLayer.get());
828 virtual void beginTest() OVERRIDE
830 m_layerTreeHost->setViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
831 m_layerTreeHost->rootLayer()->addChild(m_updateCheckLayer);
833 postSetNeedsCommitToMainThread();
836 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
838 endTest();
841 virtual void afterTest() OVERRIDE
843 // update() should have been called once.
844 EXPECT_EQ(1, m_updateCheckLayer->paintContentsCount());
846 // clear m_updateCheckLayer so LayerTreeHost dies.
847 m_updateCheckLayer = NULL;
850 private:
851 TestOpacityChangeLayerDelegate m_testOpacityChangeDelegate;
852 scoped_refptr<ContentLayerWithUpdateTracking> m_updateCheckLayer;
855 TEST_F(LayerTreeHostTestOpacityChange, runMultiThread)
857 runTest(true);
860 class NoScaleContentLayer : public ContentLayer {
861 public:
862 static scoped_refptr<NoScaleContentLayer> create(ContentLayerClient* client) { return make_scoped_refptr(new NoScaleContentLayer(client)); }
864 virtual void calculateContentsScale(
865 float idealContentsScale,
866 float* contentsScaleX,
867 float* contentsScaleY,
868 gfx::Size* contentBounds) OVERRIDE
870 Layer::calculateContentsScale(
871 idealContentsScale,
872 contentsScaleX,
873 contentsScaleY,
874 contentBounds);
877 private:
878 explicit NoScaleContentLayer(ContentLayerClient* client)
879 : ContentLayer(client) { }
880 virtual ~NoScaleContentLayer() { }
883 class LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers : public LayerTreeHostTest {
884 public:
886 LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers()
887 : m_rootLayer(NoScaleContentLayer::create(&m_client))
888 , m_childLayer(ContentLayer::create(&m_client))
892 virtual void beginTest() OVERRIDE
894 m_layerTreeHost->setViewportSize(gfx::Size(40, 40), gfx::Size(60, 60));
895 m_layerTreeHost->setDeviceScaleFactor(1.5);
896 EXPECT_EQ(gfx::Size(40, 40), m_layerTreeHost->layoutViewportSize());
897 EXPECT_EQ(gfx::Size(60, 60), m_layerTreeHost->deviceViewportSize());
899 m_rootLayer->addChild(m_childLayer);
901 m_rootLayer->setIsDrawable(true);
902 m_rootLayer->setBounds(gfx::Size(30, 30));
903 m_rootLayer->setAnchorPoint(gfx::PointF(0, 0));
905 m_childLayer->setIsDrawable(true);
906 m_childLayer->setPosition(gfx::Point(2, 2));
907 m_childLayer->setBounds(gfx::Size(10, 10));
908 m_childLayer->setAnchorPoint(gfx::PointF(0, 0));
910 m_layerTreeHost->setRootLayer(m_rootLayer);
912 ASSERT_TRUE(m_layerTreeHost->initializeRendererIfNeeded());
913 ResourceUpdateQueue queue;
914 m_layerTreeHost->updateLayers(queue, std::numeric_limits<size_t>::max());
915 postSetNeedsCommitToMainThread();
918 virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE
920 // Get access to protected methods.
921 MockLayerTreeHostImpl* mockImpl = static_cast<MockLayerTreeHostImpl*>(impl);
923 // Should only do one commit.
924 EXPECT_EQ(0, impl->activeTree()->source_frame_number());
925 // Device scale factor should come over to impl.
926 EXPECT_NEAR(impl->deviceScaleFactor(), 1.5, 0.00001);
928 // Both layers are on impl.
929 ASSERT_EQ(1u, impl->rootLayer()->children().size());
931 // Device viewport is scaled.
932 EXPECT_EQ(gfx::Size(40, 40), impl->layoutViewportSize());
933 EXPECT_EQ(gfx::Size(60, 60), impl->deviceViewportSize());
935 LayerImpl* root = impl->rootLayer();
936 LayerImpl* child = impl->rootLayer()->children()[0];
938 // Positions remain in layout pixels.
939 EXPECT_EQ(gfx::Point(0, 0), root->position());
940 EXPECT_EQ(gfx::Point(2, 2), child->position());
942 // Compute all the layer transforms for the frame.
943 LayerTreeHostImpl::FrameData frameData;
944 mockImpl->prepareToDraw(frameData);
945 mockImpl->didDrawAllLayers(frameData);
947 const MockLayerTreeHostImpl::LayerList& renderSurfaceLayerList =
948 *frameData.renderSurfaceLayerList;
950 // Both layers should be drawing into the root render surface.
951 ASSERT_EQ(1u, renderSurfaceLayerList.size());
952 ASSERT_EQ(root->renderSurface(), renderSurfaceLayerList[0]->renderSurface());
953 ASSERT_EQ(2u, root->renderSurface()->layerList().size());
955 // The root render surface is the size of the viewport.
956 EXPECT_RECT_EQ(gfx::Rect(0, 0, 60, 60), root->renderSurface()->contentRect());
958 // The content bounds of the child should be scaled.
959 gfx::Size childBoundsScaled = gfx::ToCeiledSize(gfx::ScaleSize(child->bounds(), 1.5));
960 EXPECT_EQ(childBoundsScaled, child->contentBounds());
962 gfx::Transform scaleTransform;
963 scaleTransform.Scale(impl->deviceScaleFactor(), impl->deviceScaleFactor());
965 // The root layer is scaled by 2x.
966 gfx::Transform rootScreenSpaceTransform = scaleTransform;
967 gfx::Transform rootDrawTransform = scaleTransform;
969 EXPECT_EQ(rootDrawTransform, root->drawTransform());
970 EXPECT_EQ(rootScreenSpaceTransform, root->screenSpaceTransform());
972 // The child is at position 2,2, which is transformed to 3,3 after the scale
973 gfx::Transform childScreenSpaceTransform;
974 childScreenSpaceTransform.Translate(3, 3);
975 gfx::Transform childDrawTransform = childScreenSpaceTransform;
977 EXPECT_TRANSFORMATION_MATRIX_EQ(childDrawTransform, child->drawTransform());
978 EXPECT_TRANSFORMATION_MATRIX_EQ(childScreenSpaceTransform, child->screenSpaceTransform());
980 endTest();
983 virtual void afterTest() OVERRIDE
985 m_rootLayer = NULL;
986 m_childLayer = NULL;
989 private:
990 FakeContentLayerClient m_client;
991 scoped_refptr<NoScaleContentLayer> m_rootLayer;
992 scoped_refptr<ContentLayer> m_childLayer;
995 TEST_F(LayerTreeHostTestDeviceScaleFactorScalesViewportAndLayers, runMultiThread)
997 runTest(true);
1000 // Verify atomicity of commits and reuse of textures.
1001 class LayerTreeHostTestAtomicCommit : public LayerTreeHostTest {
1002 public:
1003 LayerTreeHostTestAtomicCommit()
1005 // Make sure partial texture updates are turned off.
1006 m_settings.maxPartialTextureUpdates = 0;
1007 // Linear fade animator prevents scrollbars from drawing immediately.
1008 m_settings.useLinearFadeScrollbarAnimator = false;
1011 virtual void setupTree() OVERRIDE
1013 m_layer = FakeContentLayer::Create(&m_client);
1014 m_layer->setBounds(gfx::Size(10, 20));
1016 bool paint_scrollbar = true;
1017 bool has_thumb = false;
1018 m_scrollbar = FakeScrollbarLayer::Create(
1019 paint_scrollbar, has_thumb, m_layer->id());
1020 m_scrollbar->setPosition(gfx::Point(0, 10));
1021 m_scrollbar->setBounds(gfx::Size(10, 10));
1023 m_layer->addChild(m_scrollbar);
1025 m_layerTreeHost->setRootLayer(m_layer);
1026 LayerTreeHostTest::setupTree();
1029 virtual void beginTest() OVERRIDE
1031 postSetNeedsCommitToMainThread();
1034 virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE
1036 ASSERT_EQ(0u, m_layerTreeHost->settings().maxPartialTextureUpdates);
1038 FakeWebGraphicsContext3D* context = static_cast<FakeWebGraphicsContext3D*>(impl->outputSurface()->Context3D());
1040 switch (impl->activeTree()->source_frame_number()) {
1041 case 0:
1042 // Number of textures should be one for each layer
1043 ASSERT_EQ(2, context->NumTextures());
1044 // Number of textures used for commit should be one for each layer.
1045 EXPECT_EQ(2, context->NumUsedTextures());
1046 // Verify that used texture is correct.
1047 EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
1048 EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
1050 context->ResetUsedTextures();
1051 postSetNeedsCommitToMainThread();
1052 break;
1053 case 1:
1054 // Number of textures should be doubled as the first textures
1055 // are used by impl thread and cannot by used for update.
1056 ASSERT_EQ(4, context->NumTextures());
1057 // Number of textures used for commit should still be one for each layer.
1058 EXPECT_EQ(2, context->NumUsedTextures());
1059 // First textures should not have been used.
1060 EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
1061 EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
1062 // New textures should have been used.
1063 EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
1064 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1066 context->ResetUsedTextures();
1067 postSetNeedsCommitToMainThread();
1068 break;
1069 case 2:
1070 endTest();
1071 break;
1072 default:
1073 NOTREACHED();
1074 break;
1078 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
1080 FakeWebGraphicsContext3D* context = static_cast<FakeWebGraphicsContext3D*>(impl->outputSurface()->Context3D());
1082 // Number of textures used for draw should always be one for each layer.
1083 EXPECT_EQ(2, context->NumUsedTextures());
1084 context->ResetUsedTextures();
1087 virtual void layout() OVERRIDE
1089 m_layer->setNeedsDisplay();
1090 m_scrollbar->setNeedsDisplay();
1093 virtual void afterTest() OVERRIDE
1097 private:
1098 FakeContentLayerClient m_client;
1099 scoped_refptr<FakeContentLayer> m_layer;
1100 scoped_refptr<FakeScrollbarLayer> m_scrollbar;
1103 TEST_F(LayerTreeHostTestAtomicCommit, runMultiThread)
1105 runTest(true);
1108 static void setLayerPropertiesForTesting(Layer* layer, Layer* parent, const gfx::Transform& transform, const gfx::PointF& anchor, const gfx::PointF& position, const gfx::Size& bounds, bool opaque)
1110 layer->removeAllChildren();
1111 if (parent)
1112 parent->addChild(layer);
1113 layer->setTransform(transform);
1114 layer->setAnchorPoint(anchor);
1115 layer->setPosition(position);
1116 layer->setBounds(bounds);
1117 layer->setContentsOpaque(opaque);
1120 class LayerTreeHostTestAtomicCommitWithPartialUpdate : public LayerTreeHostTest {
1121 public:
1122 LayerTreeHostTestAtomicCommitWithPartialUpdate()
1123 : m_numCommits(0)
1125 // Allow one partial texture update.
1126 m_settings.maxPartialTextureUpdates = 1;
1127 // Linear fade animator prevents scrollbars from drawing immediately.
1128 m_settings.useLinearFadeScrollbarAnimator = false;
1131 virtual void setupTree() OVERRIDE
1133 m_parent = FakeContentLayer::Create(&m_client);
1134 m_parent->setBounds(gfx::Size(10, 20));
1136 m_child = FakeContentLayer::Create(&m_client);
1137 m_child->setPosition(gfx::Point(0, 10));
1138 m_child->setBounds(gfx::Size(3, 10));
1140 bool paint_scrollbar = true;
1141 bool has_thumb = false;
1142 m_scrollbarWithPaints = FakeScrollbarLayer::Create(
1143 paint_scrollbar, has_thumb, m_parent->id());
1144 m_scrollbarWithPaints->setPosition(gfx::Point(3, 10));
1145 m_scrollbarWithPaints->setBounds(gfx::Size(3, 10));
1147 paint_scrollbar = false;
1148 m_scrollbarWithoutPaints = FakeScrollbarLayer::Create(
1149 paint_scrollbar, has_thumb, m_parent->id());
1150 m_scrollbarWithoutPaints->setPosition(gfx::Point(6, 10));
1151 m_scrollbarWithoutPaints->setBounds(gfx::Size(3, 10));
1153 m_parent->addChild(m_child);
1154 m_parent->addChild(m_scrollbarWithPaints);
1155 m_parent->addChild(m_scrollbarWithoutPaints);
1157 m_layerTreeHost->setRootLayer(m_parent);
1158 LayerTreeHostTest::setupTree();
1161 virtual void beginTest() OVERRIDE
1163 postSetNeedsCommitToMainThread();
1166 virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE
1168 ASSERT_EQ(1u, m_layerTreeHost->settings().maxPartialTextureUpdates);
1170 FakeWebGraphicsContext3D* context = static_cast<FakeWebGraphicsContext3D*>(impl->outputSurface()->Context3D());
1172 switch (impl->activeTree()->source_frame_number()) {
1173 case 0:
1174 // Number of textures should be one for each layer.
1175 ASSERT_EQ(4, context->NumTextures());
1176 // Number of textures used for commit should be one for each layer.
1177 EXPECT_EQ(4, context->NumUsedTextures());
1178 // Verify that used textures are correct.
1179 EXPECT_TRUE(context->UsedTexture(context->TextureAt(0)));
1180 EXPECT_TRUE(context->UsedTexture(context->TextureAt(1)));
1181 EXPECT_TRUE(context->UsedTexture(context->TextureAt(2)));
1182 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1184 context->ResetUsedTextures();
1185 postSetNeedsCommitToMainThread();
1186 break;
1187 case 1:
1188 // Number of textures should be two for each content layer and one
1189 // for each scrollbar, since they always do a partial update.
1190 ASSERT_EQ(6, context->NumTextures());
1191 // Number of textures used for commit should be one for each content
1192 // layer, and one for the scrollbar layer that paints.
1193 EXPECT_EQ(3, context->NumUsedTextures());
1195 // First content textures should not have been used.
1196 EXPECT_FALSE(context->UsedTexture(context->TextureAt(0)));
1197 EXPECT_FALSE(context->UsedTexture(context->TextureAt(1)));
1198 // The non-painting scrollbar's texture wasn't updated.
1199 EXPECT_FALSE(context->UsedTexture(context->TextureAt(2)));
1200 // The painting scrollbar's partial update texture was used.
1201 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1202 // New textures should have been used.
1203 EXPECT_TRUE(context->UsedTexture(context->TextureAt(4)));
1204 EXPECT_TRUE(context->UsedTexture(context->TextureAt(5)));
1206 context->ResetUsedTextures();
1207 postSetNeedsCommitToMainThread();
1208 break;
1209 case 2:
1210 // Number of textures should be two for each content layer and one
1211 // for each scrollbar, since they always do a partial update.
1212 ASSERT_EQ(6, context->NumTextures());
1213 // Number of textures used for commit should be one for each content
1214 // layer, and one for the scrollbar layer that paints.
1215 EXPECT_EQ(3, context->NumUsedTextures());
1217 // The non-painting scrollbar's texture wasn't updated.
1218 EXPECT_FALSE(context->UsedTexture(context->TextureAt(2)));
1219 // The painting scrollbar does a partial update.
1220 EXPECT_TRUE(context->UsedTexture(context->TextureAt(3)));
1221 // One content layer does a partial update also.
1222 EXPECT_TRUE(context->UsedTexture(context->TextureAt(4)));
1223 EXPECT_FALSE(context->UsedTexture(context->TextureAt(5)));
1225 context->ResetUsedTextures();
1226 postSetNeedsCommitToMainThread();
1227 break;
1228 case 3:
1229 // No textures should be used for commit.
1230 EXPECT_EQ(0, context->NumUsedTextures());
1232 context->ResetUsedTextures();
1233 postSetNeedsCommitToMainThread();
1234 break;
1235 case 4:
1236 // Number of textures used for commit should be two. One for the
1237 // content layer, and one for the painting scrollbar. The
1238 // non-painting scrollbar doesn't update its texture.
1239 EXPECT_EQ(2, context->NumUsedTextures());
1241 context->ResetUsedTextures();
1242 postSetNeedsCommitToMainThread();
1243 break;
1244 case 5:
1245 endTest();
1246 break;
1247 default:
1248 NOTREACHED();
1249 break;
1253 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
1255 FakeWebGraphicsContext3D* context = static_cast<FakeWebGraphicsContext3D*>(impl->outputSurface()->Context3D());
1257 // Number of textures used for drawing should one per layer except for
1258 // frame 3 where the viewport only contains one layer.
1259 if (impl->activeTree()->source_frame_number() == 3)
1260 EXPECT_EQ(1, context->NumUsedTextures());
1261 else
1262 EXPECT_EQ(4, context->NumUsedTextures());
1264 context->ResetUsedTextures();
1267 virtual void layout() OVERRIDE
1269 switch (m_numCommits++) {
1270 case 0:
1271 case 1:
1272 m_parent->setNeedsDisplay();
1273 m_child->setNeedsDisplay();
1274 m_scrollbarWithPaints->setNeedsDisplay();
1275 m_scrollbarWithoutPaints->setNeedsDisplay();
1276 break;
1277 case 2:
1278 // Damage part of layers.
1279 m_parent->setNeedsDisplayRect(gfx::RectF(0, 0, 5, 5));
1280 m_child->setNeedsDisplayRect(gfx::RectF(0, 0, 5, 5));
1281 m_scrollbarWithPaints->setNeedsDisplayRect(gfx::RectF(0, 0, 5, 5));
1282 m_scrollbarWithoutPaints->setNeedsDisplayRect(gfx::RectF(0, 0, 5, 5));
1283 break;
1284 case 3:
1285 m_child->setNeedsDisplay();
1286 m_scrollbarWithPaints->setNeedsDisplay();
1287 m_scrollbarWithoutPaints->setNeedsDisplay();
1288 m_layerTreeHost->setViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
1289 break;
1290 case 4:
1291 m_layerTreeHost->setViewportSize(gfx::Size(10, 20), gfx::Size(10, 20));
1292 break;
1293 case 5:
1294 break;
1295 default:
1296 NOTREACHED();
1297 break;
1301 virtual void afterTest() OVERRIDE
1305 private:
1306 FakeContentLayerClient m_client;
1307 scoped_refptr<FakeContentLayer> m_parent;
1308 scoped_refptr<FakeContentLayer> m_child;
1309 scoped_refptr<FakeScrollbarLayer> m_scrollbarWithPaints;
1310 scoped_refptr<FakeScrollbarLayer> m_scrollbarWithoutPaints;
1311 int m_numCommits;
1314 TEST_F(LayerTreeHostTestAtomicCommitWithPartialUpdate, runMultiThread)
1316 runTest(true);
1319 class LayerTreeHostTestFinishAllRendering : public LayerTreeHostTest {
1320 public:
1321 LayerTreeHostTestFinishAllRendering()
1322 : m_once(false)
1323 , m_drawCount(0)
1327 virtual void beginTest() OVERRIDE
1329 m_layerTreeHost->setNeedsRedraw();
1330 postSetNeedsCommitToMainThread();
1333 virtual void didCommitAndDrawFrame() OVERRIDE
1335 if (m_once)
1336 return;
1337 m_once = true;
1338 m_layerTreeHost->setNeedsRedraw();
1339 m_layerTreeHost->acquireLayerTextures();
1341 base::AutoLock lock(m_lock);
1342 m_drawCount = 0;
1344 m_layerTreeHost->finishAllRendering();
1346 base::AutoLock lock(m_lock);
1347 EXPECT_EQ(0, m_drawCount);
1349 endTest();
1352 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
1354 base::AutoLock lock(m_lock);
1355 ++m_drawCount;
1358 virtual void afterTest() OVERRIDE
1361 private:
1363 bool m_once;
1364 base::Lock m_lock;
1365 int m_drawCount;
1368 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestFinishAllRendering)
1370 class LayerTreeHostTestCompositeAndReadbackCleanup : public LayerTreeHostTest {
1371 public:
1372 LayerTreeHostTestCompositeAndReadbackCleanup() { }
1374 virtual void beginTest() OVERRIDE
1376 Layer* rootLayer = m_layerTreeHost->rootLayer();
1378 char pixels[4];
1379 m_layerTreeHost->compositeAndReadback(static_cast<void*>(&pixels), gfx::Rect(0, 0, 1, 1));
1380 EXPECT_FALSE(rootLayer->renderSurface());
1382 endTest();
1385 virtual void afterTest() OVERRIDE
1390 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestCompositeAndReadbackCleanup)
1392 class LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit : public LayerTreeHostTest {
1393 public:
1394 LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit()
1395 : m_rootLayer(ContentLayerWithUpdateTracking::create(&m_fakeDelegate))
1396 , m_surfaceLayer1(ContentLayerWithUpdateTracking::create(&m_fakeDelegate))
1397 , m_replicaLayer1(ContentLayerWithUpdateTracking::create(&m_fakeDelegate))
1398 , m_surfaceLayer2(ContentLayerWithUpdateTracking::create(&m_fakeDelegate))
1399 , m_replicaLayer2(ContentLayerWithUpdateTracking::create(&m_fakeDelegate))
1403 virtual void beginTest() OVERRIDE
1405 m_layerTreeHost->setViewportSize(gfx::Size(100, 100), gfx::Size(100, 100));
1407 m_rootLayer->setBounds(gfx::Size(100, 100));
1408 m_surfaceLayer1->setBounds(gfx::Size(100, 100));
1409 m_surfaceLayer1->setForceRenderSurface(true);
1410 m_surfaceLayer1->setOpacity(0.5);
1411 m_surfaceLayer2->setBounds(gfx::Size(100, 100));
1412 m_surfaceLayer2->setForceRenderSurface(true);
1413 m_surfaceLayer2->setOpacity(0.5);
1415 m_surfaceLayer1->setReplicaLayer(m_replicaLayer1.get());
1416 m_surfaceLayer2->setReplicaLayer(m_replicaLayer2.get());
1418 m_rootLayer->addChild(m_surfaceLayer1);
1419 m_surfaceLayer1->addChild(m_surfaceLayer2);
1420 m_layerTreeHost->setRootLayer(m_rootLayer);
1422 postSetNeedsCommitToMainThread();
1425 virtual void drawLayersOnThread(LayerTreeHostImpl* hostImpl) OVERRIDE
1427 Renderer* renderer = hostImpl->renderer();
1428 RenderPass::Id surface1RenderPassId = hostImpl->rootLayer()->children()[0]->renderSurface()->renderPassId();
1429 RenderPass::Id surface2RenderPassId = hostImpl->rootLayer()->children()[0]->children()[0]->renderSurface()->renderPassId();
1431 switch (hostImpl->activeTree()->source_frame_number()) {
1432 case 0:
1433 EXPECT_TRUE(renderer->haveCachedResourcesForRenderPassId(surface1RenderPassId));
1434 EXPECT_TRUE(renderer->haveCachedResourcesForRenderPassId(surface2RenderPassId));
1436 // Reduce the memory limit to only fit the root layer and one render surface. This
1437 // prevents any contents drawing into surfaces from being allocated.
1438 hostImpl->setManagedMemoryPolicy(ManagedMemoryPolicy(100 * 100 * 4 * 2));
1439 break;
1440 case 1:
1441 EXPECT_FALSE(renderer->haveCachedResourcesForRenderPassId(surface1RenderPassId));
1442 EXPECT_FALSE(renderer->haveCachedResourcesForRenderPassId(surface2RenderPassId));
1444 endTest();
1445 break;
1449 virtual void afterTest() OVERRIDE
1451 EXPECT_EQ(2, m_rootLayer->paintContentsCount());
1452 EXPECT_EQ(2, m_surfaceLayer1->paintContentsCount());
1453 EXPECT_EQ(2, m_surfaceLayer2->paintContentsCount());
1455 // Clear layer references so LayerTreeHost dies.
1456 m_rootLayer = NULL;
1457 m_surfaceLayer1 = NULL;
1458 m_replicaLayer1 = NULL;
1459 m_surfaceLayer2 = NULL;
1460 m_replicaLayer2 = NULL;
1463 private:
1464 FakeContentLayerClient m_fakeDelegate;
1465 scoped_refptr<ContentLayerWithUpdateTracking> m_rootLayer;
1466 scoped_refptr<ContentLayerWithUpdateTracking> m_surfaceLayer1;
1467 scoped_refptr<ContentLayerWithUpdateTracking> m_replicaLayer1;
1468 scoped_refptr<ContentLayerWithUpdateTracking> m_surfaceLayer2;
1469 scoped_refptr<ContentLayerWithUpdateTracking> m_replicaLayer2;
1472 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestSurfaceNotAllocatedForLayersOutsideMemoryLimit)
1474 class EvictionTestLayer : public Layer {
1475 public:
1476 static scoped_refptr<EvictionTestLayer> create() { return make_scoped_refptr(new EvictionTestLayer()); }
1478 virtual void update(ResourceUpdateQueue&, const OcclusionTracker*, RenderingStats&) OVERRIDE;
1479 virtual bool drawsContent() const OVERRIDE { return true; }
1481 virtual scoped_ptr<LayerImpl> createLayerImpl(LayerTreeImpl* treeImpl) OVERRIDE;
1482 virtual void pushPropertiesTo(LayerImpl*) OVERRIDE;
1483 virtual void setTexturePriorities(const PriorityCalculator&) OVERRIDE;
1485 bool haveBackingTexture() const { return m_texture.get() ? m_texture->haveBackingTexture() : false; }
1487 private:
1488 EvictionTestLayer() : Layer() { }
1489 virtual ~EvictionTestLayer() { }
1491 void createTextureIfNeeded()
1493 if (m_texture.get())
1494 return;
1495 m_texture = PrioritizedResource::create(layerTreeHost()->contentsTextureManager());
1496 m_texture->setDimensions(gfx::Size(10, 10), GL_RGBA);
1497 m_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
1500 scoped_ptr<PrioritizedResource> m_texture;
1501 SkBitmap m_bitmap;
1504 class EvictionTestLayerImpl : public LayerImpl {
1505 public:
1506 static scoped_ptr<EvictionTestLayerImpl> create(LayerTreeImpl* treeImpl, int id)
1508 return make_scoped_ptr(new EvictionTestLayerImpl(treeImpl, id));
1510 virtual ~EvictionTestLayerImpl() { }
1512 virtual void appendQuads(QuadSink& quadSink, AppendQuadsData&) OVERRIDE
1514 ASSERT_TRUE(m_hasTexture);
1515 ASSERT_NE(0u, layerTreeImpl()->resource_provider()->numResources());
1518 void setHasTexture(bool hasTexture) { m_hasTexture = hasTexture; }
1520 private:
1521 EvictionTestLayerImpl(LayerTreeImpl* treeImpl, int id)
1522 : LayerImpl(treeImpl, id)
1523 , m_hasTexture(false) { }
1525 bool m_hasTexture;
1528 void EvictionTestLayer::setTexturePriorities(const PriorityCalculator&)
1530 createTextureIfNeeded();
1531 if (!m_texture.get())
1532 return;
1533 m_texture->setRequestPriority(PriorityCalculator::uiPriority(true));
1536 void EvictionTestLayer::update(ResourceUpdateQueue& queue, const OcclusionTracker*, RenderingStats&)
1538 createTextureIfNeeded();
1539 if (!m_texture.get())
1540 return;
1542 gfx::Rect fullRect(0, 0, 10, 10);
1543 ResourceUpdate upload = ResourceUpdate::Create(
1544 m_texture.get(), &m_bitmap, fullRect, fullRect, gfx::Vector2d());
1545 queue.appendFullUpload(upload);
1548 scoped_ptr<LayerImpl> EvictionTestLayer::createLayerImpl(LayerTreeImpl* treeImpl)
1550 return EvictionTestLayerImpl::create(treeImpl, m_layerId).PassAs<LayerImpl>();
1553 void EvictionTestLayer::pushPropertiesTo(LayerImpl* layerImpl)
1555 Layer::pushPropertiesTo(layerImpl);
1557 EvictionTestLayerImpl* testLayerImpl = static_cast<EvictionTestLayerImpl*>(layerImpl);
1558 testLayerImpl->setHasTexture(m_texture->haveBackingTexture());
1561 class LayerTreeHostTestEvictTextures : public LayerTreeHostTest {
1562 public:
1563 LayerTreeHostTestEvictTextures()
1564 : m_layer(EvictionTestLayer::create())
1565 , m_implForEvictTextures(0)
1566 , m_numCommits(0)
1570 virtual void beginTest() OVERRIDE
1572 m_layerTreeHost->setRootLayer(m_layer);
1573 m_layerTreeHost->setViewportSize(gfx::Size(10, 20), gfx::Size(10, 20));
1575 gfx::Transform identityMatrix;
1576 setLayerPropertiesForTesting(m_layer.get(), 0, identityMatrix, gfx::PointF(0, 0), gfx::PointF(0, 0), gfx::Size(10, 20), true);
1578 postSetNeedsCommitToMainThread();
1581 void postEvictTextures()
1583 DCHECK(implThread());
1584 implThread()->postTask(base::Bind(&LayerTreeHostTestEvictTextures::evictTexturesOnImplThread,
1585 base::Unretained(this)));
1588 void evictTexturesOnImplThread()
1590 DCHECK(m_implForEvictTextures);
1591 m_implForEvictTextures->enforceManagedMemoryPolicy(ManagedMemoryPolicy(0));
1594 // Commit 1: Just commit and draw normally, then post an eviction at the end
1595 // that will trigger a commit.
1596 // Commit 2: Triggered by the eviction, let it go through and then set
1597 // needsCommit.
1598 // Commit 3: Triggered by the setNeedsCommit. In layout(), post an eviction
1599 // task, which will be handled before the commit. Don't set needsCommit, it
1600 // should have been posted. A frame should not be drawn (note,
1601 // didCommitAndDrawFrame may be called anyway).
1602 // Commit 4: Triggered by the eviction, let it go through and then set
1603 // needsCommit.
1604 // Commit 5: Triggered by the setNeedsCommit, post an eviction task in
1605 // layout(), a frame should not be drawn but a commit will be posted.
1606 // Commit 6: Triggered by the eviction, post an eviction task in
1607 // layout(), which will be a noop, letting the commit (which recreates the
1608 // textures) go through and draw a frame, then end the test.
1610 // Commits 1+2 test the eviction recovery path where eviction happens outside
1611 // of the beginFrame/commit pair.
1612 // Commits 3+4 test the eviction recovery path where eviction happens inside
1613 // the beginFrame/commit pair.
1614 // Commits 5+6 test the path where an eviction happens during the eviction
1615 // recovery path.
1616 virtual void didCommitAndDrawFrame() OVERRIDE
1618 switch (m_numCommits) {
1619 case 1:
1620 EXPECT_TRUE(m_layer->haveBackingTexture());
1621 postEvictTextures();
1622 break;
1623 case 2:
1624 EXPECT_TRUE(m_layer->haveBackingTexture());
1625 m_layerTreeHost->setNeedsCommit();
1626 break;
1627 case 3:
1628 break;
1629 case 4:
1630 EXPECT_TRUE(m_layer->haveBackingTexture());
1631 m_layerTreeHost->setNeedsCommit();
1632 break;
1633 case 5:
1634 break;
1635 case 6:
1636 EXPECT_TRUE(m_layer->haveBackingTexture());
1637 endTest();
1638 break;
1639 default:
1640 NOTREACHED();
1641 break;
1645 virtual void commitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE
1647 m_implForEvictTextures = impl;
1650 virtual void layout() OVERRIDE
1652 ++m_numCommits;
1653 switch (m_numCommits) {
1654 case 1:
1655 case 2:
1656 break;
1657 case 3:
1658 postEvictTextures();
1659 break;
1660 case 4:
1661 // We couldn't check in didCommitAndDrawFrame on commit 3, so check here.
1662 EXPECT_FALSE(m_layer->haveBackingTexture());
1663 break;
1664 case 5:
1665 postEvictTextures();
1666 break;
1667 case 6:
1668 // We couldn't check in didCommitAndDrawFrame on commit 5, so check here.
1669 EXPECT_FALSE(m_layer->haveBackingTexture());
1670 postEvictTextures();
1671 break;
1672 default:
1673 NOTREACHED();
1674 break;
1678 virtual void afterTest() OVERRIDE
1682 private:
1683 FakeContentLayerClient m_client;
1684 scoped_refptr<EvictionTestLayer> m_layer;
1685 LayerTreeHostImpl* m_implForEvictTextures;
1686 int m_numCommits;
1689 TEST_F(LayerTreeHostTestEvictTextures, runMultiThread)
1691 runTest(true);
1694 class LayerTreeHostTestContinuousCommit : public LayerTreeHostTest {
1695 public:
1696 LayerTreeHostTestContinuousCommit()
1697 : m_numCommitComplete(0)
1698 , m_numDrawLayers(0)
1702 virtual void beginTest() OVERRIDE
1704 m_layerTreeHost->setViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
1705 m_layerTreeHost->rootLayer()->setBounds(gfx::Size(10, 10));
1707 postSetNeedsCommitToMainThread();
1710 virtual void didCommit() OVERRIDE
1712 if (m_numDrawLayers == 2)
1713 return;
1714 postSetNeedsCommitToMainThread();
1717 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
1719 if (m_numDrawLayers == 1)
1720 m_numCommitComplete++;
1723 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
1725 m_numDrawLayers++;
1726 if (m_numDrawLayers == 2)
1727 endTest();
1730 virtual void afterTest() OVERRIDE
1732 // Check that we didn't commit twice between first and second draw.
1733 EXPECT_EQ(1, m_numCommitComplete);
1736 private:
1737 int m_numCommitComplete;
1738 int m_numDrawLayers;
1741 TEST_F(LayerTreeHostTestContinuousCommit, runMultiThread)
1743 runTest(true);
1746 class LayerTreeHostTestContinuousInvalidate : public LayerTreeHostTest {
1747 public:
1748 LayerTreeHostTestContinuousInvalidate()
1749 : m_numCommitComplete(0)
1750 , m_numDrawLayers(0)
1754 virtual void beginTest() OVERRIDE
1756 m_layerTreeHost->setViewportSize(gfx::Size(10, 10), gfx::Size(10, 10));
1757 m_layerTreeHost->rootLayer()->setBounds(gfx::Size(10, 10));
1759 m_contentLayer = ContentLayer::create(&m_fakeDelegate);
1760 m_contentLayer->setBounds(gfx::Size(10, 10));
1761 m_contentLayer->setPosition(gfx::PointF(0, 0));
1762 m_contentLayer->setAnchorPoint(gfx::PointF(0, 0));
1763 m_contentLayer->setIsDrawable(true);
1764 m_layerTreeHost->rootLayer()->addChild(m_contentLayer);
1766 postSetNeedsCommitToMainThread();
1769 virtual void didCommit() OVERRIDE
1771 if (m_numDrawLayers == 2)
1772 return;
1773 m_contentLayer->setNeedsDisplay();
1776 virtual void commitCompleteOnThread(LayerTreeHostImpl*) OVERRIDE
1778 if (m_numDrawLayers == 1)
1779 m_numCommitComplete++;
1782 virtual void drawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE
1784 m_numDrawLayers++;
1785 if (m_numDrawLayers == 2)
1786 endTest();
1789 virtual void afterTest() OVERRIDE
1791 // Check that we didn't commit twice between first and second draw.
1792 EXPECT_EQ(1, m_numCommitComplete);
1794 // Clear layer references so LayerTreeHost dies.
1795 m_contentLayer = NULL;
1798 private:
1799 FakeContentLayerClient m_fakeDelegate;
1800 scoped_refptr<Layer> m_contentLayer;
1801 int m_numCommitComplete;
1802 int m_numDrawLayers;
1805 TEST_F(LayerTreeHostTestContinuousInvalidate, runMultiThread)
1807 runTest(true);
1810 class LayerTreeHostTestAdjustPointForZoom : public LayerTreeHostTest {
1811 public:
1812 LayerTreeHostTestAdjustPointForZoom()
1816 virtual void beginTest() OVERRIDE
1818 gfx::Transform m;
1819 m.Translate(250, 360);
1820 m.Scale(2, 2);
1822 gfx::Point point(400, 550);
1823 gfx::Point transformedPoint;
1825 // Unit transform, no change expected.
1826 m_layerTreeHost->setImplTransform(gfx::Transform());
1827 transformedPoint = gfx::ToRoundedPoint(m_layerTreeHost->adjustEventPointForPinchZoom(point));
1828 EXPECT_EQ(point.x(), transformedPoint.x());
1829 EXPECT_EQ(point.y(), transformedPoint.y());
1831 m_layerTreeHost->setImplTransform(m);
1833 // Apply m^(-1): 75 = (400 - 250) / 2; 95 = (550 - 360) / 2.
1834 transformedPoint = gfx::ToRoundedPoint(m_layerTreeHost->adjustEventPointForPinchZoom(point));
1835 EXPECT_EQ(75, transformedPoint.x());
1836 EXPECT_EQ(95, transformedPoint.y());
1837 endTest();
1840 virtual void afterTest() OVERRIDE
1845 TEST_F(LayerTreeHostTestAdjustPointForZoom, runMultiThread)
1847 runTest(true);
1850 class LayerTreeHostTestDeferCommits : public LayerTreeHostTest {
1851 public:
1852 LayerTreeHostTestDeferCommits()
1853 : m_numCommitsDeferred(0)
1854 , m_numCompleteCommits(0)
1858 virtual void beginTest() OVERRIDE
1860 postSetNeedsCommitToMainThread();
1863 virtual void didDeferCommit() OVERRIDE
1865 m_numCommitsDeferred++;
1866 m_layerTreeHost->setDeferCommits(false);
1869 virtual void didCommit() OVERRIDE
1871 m_numCompleteCommits++;
1872 switch (m_numCompleteCommits) {
1873 case 1:
1874 EXPECT_EQ(0, m_numCommitsDeferred);
1875 m_layerTreeHost->setDeferCommits(true);
1876 postSetNeedsCommitToMainThread();
1877 break;
1878 case 2:
1879 endTest();
1880 break;
1881 default:
1882 NOTREACHED();
1883 break;
1887 virtual void afterTest() OVERRIDE
1889 EXPECT_EQ(1, m_numCommitsDeferred);
1890 EXPECT_EQ(2, m_numCompleteCommits);
1893 private:
1894 int m_numCommitsDeferred;
1895 int m_numCompleteCommits;
1898 TEST_F(LayerTreeHostTestDeferCommits, runMultiThread)
1900 runTest(true);
1903 class LayerTreeHostWithProxy : public LayerTreeHost {
1904 public:
1905 LayerTreeHostWithProxy(FakeLayerImplTreeHostClient* client, const LayerTreeSettings& settings, scoped_ptr<Proxy> proxy)
1906 : LayerTreeHost(client, settings)
1908 EXPECT_TRUE(initializeForTesting(proxy.Pass()));
1911 private:
1912 FakeLayerImplTreeHostClient m_client;
1915 TEST(LayerTreeHostTest, LimitPartialUpdates)
1917 // When partial updates are not allowed, max updates should be 0.
1919 FakeLayerImplTreeHostClient client;
1921 scoped_ptr<FakeProxy> proxy = make_scoped_ptr(new FakeProxy(scoped_ptr<Thread>()));
1922 proxy->rendererCapabilities().allowPartialTextureUpdates = false;
1923 proxy->setMaxPartialTextureUpdates(5);
1925 LayerTreeSettings settings;
1926 settings.maxPartialTextureUpdates = 10;
1928 LayerTreeHostWithProxy host(&client, settings, proxy.PassAs<Proxy>());
1929 EXPECT_TRUE(host.initializeRendererIfNeeded());
1931 EXPECT_EQ(0u, host.settings().maxPartialTextureUpdates);
1934 // When partial updates are allowed, max updates should be limited by the proxy.
1936 FakeLayerImplTreeHostClient client;
1938 scoped_ptr<FakeProxy> proxy = make_scoped_ptr(new FakeProxy(scoped_ptr<Thread>()));
1939 proxy->rendererCapabilities().allowPartialTextureUpdates = true;
1940 proxy->setMaxPartialTextureUpdates(5);
1942 LayerTreeSettings settings;
1943 settings.maxPartialTextureUpdates = 10;
1945 LayerTreeHostWithProxy host(&client, settings, proxy.PassAs<Proxy>());
1946 EXPECT_TRUE(host.initializeRendererIfNeeded());
1948 EXPECT_EQ(5u, host.settings().maxPartialTextureUpdates);
1951 // When partial updates are allowed, max updates should also be limited by the settings.
1953 FakeLayerImplTreeHostClient client;
1955 scoped_ptr<FakeProxy> proxy = make_scoped_ptr(new FakeProxy(scoped_ptr<Thread>()));
1956 proxy->rendererCapabilities().allowPartialTextureUpdates = true;
1957 proxy->setMaxPartialTextureUpdates(20);
1959 LayerTreeSettings settings;
1960 settings.maxPartialTextureUpdates = 10;
1962 LayerTreeHostWithProxy host(&client, settings, proxy.PassAs<Proxy>());
1963 EXPECT_TRUE(host.initializeRendererIfNeeded());
1965 EXPECT_EQ(10u, host.settings().maxPartialTextureUpdates);
1969 TEST(LayerTreeHostTest, PartialUpdatesWithGLRenderer)
1971 bool useSoftwareRendering = false;
1972 bool useDelegatingRenderer = false;
1973 FakeLayerImplTreeHostClient client(useSoftwareRendering, useDelegatingRenderer);
1975 LayerTreeSettings settings;
1976 settings.maxPartialTextureUpdates = 4;
1978 scoped_ptr<LayerTreeHost> host = LayerTreeHost::create(&client, settings, scoped_ptr<Thread>());
1979 EXPECT_TRUE(host->initializeRendererIfNeeded());
1980 EXPECT_EQ(4u, host->settings().maxPartialTextureUpdates);
1983 TEST(LayerTreeHostTest, PartialUpdatesWithSoftwareRenderer)
1985 bool useSoftwareRendering = true;
1986 bool useDelegatingRenderer = false;
1987 FakeLayerImplTreeHostClient client(useSoftwareRendering, useDelegatingRenderer);
1989 LayerTreeSettings settings;
1990 settings.maxPartialTextureUpdates = 4;
1992 scoped_ptr<LayerTreeHost> host = LayerTreeHost::create(&client, settings, scoped_ptr<Thread>());
1993 EXPECT_TRUE(host->initializeRendererIfNeeded());
1994 EXPECT_EQ(4u, host->settings().maxPartialTextureUpdates);
1997 TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndGLContent)
1999 bool useSoftwareRendering = false;
2000 bool useDelegatingRenderer = true;
2001 FakeLayerImplTreeHostClient client(useSoftwareRendering, useDelegatingRenderer);
2003 LayerTreeSettings settings;
2004 settings.maxPartialTextureUpdates = 4;
2006 scoped_ptr<LayerTreeHost> host = LayerTreeHost::create(&client, settings, scoped_ptr<Thread>());
2007 EXPECT_TRUE(host->initializeRendererIfNeeded());
2008 EXPECT_EQ(0u, host->settings().maxPartialTextureUpdates);
2011 TEST(LayerTreeHostTest, PartialUpdatesWithDelegatingRendererAndSoftwareContent)
2013 bool useSoftwareRendering = true;
2014 bool useDelegatingRenderer = true;
2015 FakeLayerImplTreeHostClient client(useSoftwareRendering, useDelegatingRenderer);
2017 LayerTreeSettings settings;
2018 settings.maxPartialTextureUpdates = 4;
2020 scoped_ptr<LayerTreeHost> host = LayerTreeHost::create(&client, settings, scoped_ptr<Thread>());
2021 EXPECT_TRUE(host->initializeRendererIfNeeded());
2022 EXPECT_EQ(0u, host->settings().maxPartialTextureUpdates);
2025 class LayerTreeHostTestCapturePicture : public LayerTreeHostTest {
2026 public:
2027 LayerTreeHostTestCapturePicture()
2028 : m_bounds(gfx::Size(100, 100))
2029 , m_layer(PictureLayer::create(&m_contentClient))
2031 m_settings.implSidePainting = true;
2034 class FillRectContentLayerClient : public ContentLayerClient {
2035 public:
2036 virtual void paintContents(SkCanvas* canvas, const gfx::Rect& clip, gfx::RectF& opaque) OVERRIDE
2038 SkPaint paint;
2039 paint.setColor(SK_ColorGREEN);
2041 SkRect rect = SkRect::MakeWH(canvas->getDeviceSize().width(), canvas->getDeviceSize().height());
2042 opaque = gfx::RectF(rect.width(), rect.height());
2043 canvas->drawRect(rect, paint);
2047 virtual void beginTest() OVERRIDE
2049 m_layer->setIsDrawable(true);
2050 m_layer->setBounds(m_bounds);
2051 m_layerTreeHost->setViewportSize(m_bounds, m_bounds);
2052 m_layerTreeHost->setRootLayer(m_layer);
2054 EXPECT_TRUE(m_layerTreeHost->initializeRendererIfNeeded());
2055 postSetNeedsCommitToMainThread();
2058 virtual void didCommitAndDrawFrame() OVERRIDE
2060 m_picture = m_layerTreeHost->capturePicture();
2061 endTest();
2064 virtual void afterTest() OVERRIDE
2066 EXPECT_EQ(m_bounds, gfx::Size(m_picture->width(), m_picture->height()));
2068 SkBitmap bitmap;
2069 bitmap.setConfig(SkBitmap::kARGB_8888_Config, m_bounds.width(), m_bounds.height());
2070 bitmap.allocPixels();
2071 bitmap.eraseARGB(0, 0, 0, 0);
2072 SkCanvas canvas(bitmap);
2074 m_picture->draw(&canvas);
2076 bitmap.lockPixels();
2077 SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
2078 EXPECT_EQ(SK_ColorGREEN, pixels[0]);
2079 bitmap.unlockPixels();
2082 private:
2083 gfx::Size m_bounds;
2084 FillRectContentLayerClient m_contentClient;
2085 scoped_refptr<PictureLayer> m_layer;
2086 skia::RefPtr<SkPicture> m_picture;
2089 MULTI_THREAD_TEST_F(LayerTreeHostTestCapturePicture);
2091 } // namespace
2092 } // namespace cc