1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/layer_tree_host.h"
7 #include "cc/content_layer.h"
9 #include "cc/layer_impl.h"
10 #include "cc/layer_tree_impl.h"
11 #include "cc/test/fake_content_layer_client.h"
12 #include "cc/test/geometry_test_utils.h"
13 #include "cc/test/layer_tree_test_common.h"
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebLayerScrollClient.h"
15 #include "ui/gfx/point_conversions.h"
16 #include "ui/gfx/size_conversions.h"
17 #include "ui/gfx/vector2d_conversions.h"
22 class LayerTreeHostScrollTest
: public ThreadedTest
{};
24 class LayerTreeHostScrollTestScrollSimple
: public LayerTreeHostScrollTest
{
26 LayerTreeHostScrollTestScrollSimple()
27 : initial_scroll_(10, 20),
28 second_scroll_(40, 5),
29 scroll_amount_(2, -1),
33 virtual void beginTest() OVERRIDE
{
34 m_layerTreeHost
->rootLayer()->setScrollable(true);
35 m_layerTreeHost
->rootLayer()->setScrollOffset(initial_scroll_
);
36 postSetNeedsCommitToMainThread();
39 virtual void layout() OVERRIDE
{
40 Layer
* root
= m_layerTreeHost
->rootLayer();
41 if (!m_layerTreeHost
->commitNumber())
42 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
44 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
+ scroll_amount_
);
46 // Pretend like Javascript updated the scroll position itself.
47 root
->setScrollOffset(second_scroll_
);
51 virtual void drawLayersOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
52 LayerImpl
* root
= impl
->rootLayer();
53 EXPECT_VECTOR_EQ(root
->scrollDelta(), gfx::Vector2d());
55 root
->setScrollable(true);
56 root
->setMaxScrollOffset(gfx::Vector2d(100, 100));
57 root
->scrollBy(scroll_amount_
);
59 switch (impl
->activeTree()->source_frame_number()) {
61 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
62 EXPECT_VECTOR_EQ(root
->scrollDelta(), scroll_amount_
);
63 postSetNeedsCommitToMainThread();
66 EXPECT_VECTOR_EQ(root
->scrollOffset(), second_scroll_
);
67 EXPECT_VECTOR_EQ(root
->scrollDelta(), scroll_amount_
);
73 virtual void applyScrollAndScale(
74 gfx::Vector2d scroll_delta
, float scale
) OVERRIDE
{
75 gfx::Vector2d offset
= m_layerTreeHost
->rootLayer()->scrollOffset();
76 m_layerTreeHost
->rootLayer()->setScrollOffset(offset
+ scroll_delta
);
80 virtual void afterTest() OVERRIDE
{
81 EXPECT_EQ(1, num_scrolls_
);
85 gfx::Vector2d initial_scroll_
;
86 gfx::Vector2d second_scroll_
;
87 gfx::Vector2d scroll_amount_
;
91 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSimple
)
93 class LayerTreeHostScrollTestScrollMultipleRedraw
:
94 public LayerTreeHostScrollTest
{
96 LayerTreeHostScrollTestScrollMultipleRedraw()
97 : initial_scroll_(40, 10),
98 scroll_amount_(-3, 17),
102 virtual void beginTest() OVERRIDE
{
103 m_layerTreeHost
->rootLayer()->setScrollable(true);
104 m_layerTreeHost
->rootLayer()->setScrollOffset(initial_scroll_
);
105 postSetNeedsCommitToMainThread();
108 virtual void beginCommitOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
109 Layer
* root
= m_layerTreeHost
->rootLayer();
110 switch (m_layerTreeHost
->commitNumber()) {
112 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
116 root
->scrollOffset(),
117 initial_scroll_
+ scroll_amount_
+ scroll_amount_
);
120 root
->scrollOffset(),
121 initial_scroll_
+ scroll_amount_
+ scroll_amount_
);
126 virtual void drawLayersOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
127 LayerImpl
* root
= impl
->rootLayer();
128 root
->setScrollable(true);
129 root
->setMaxScrollOffset(gfx::Vector2d(100, 100));
131 if (impl
->activeTree()->source_frame_number() == 0 &&
132 impl
->sourceAnimationFrameNumber() == 1) {
133 // First draw after first commit.
134 EXPECT_VECTOR_EQ(root
->scrollDelta(), gfx::Vector2d());
135 root
->scrollBy(scroll_amount_
);
136 EXPECT_VECTOR_EQ(root
->scrollDelta(), scroll_amount_
);
138 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
139 postSetNeedsRedrawToMainThread();
140 } else if (impl
->activeTree()->source_frame_number() == 0 &&
141 impl
->sourceAnimationFrameNumber() == 2) {
142 // Second draw after first commit.
143 EXPECT_EQ(root
->scrollDelta(), scroll_amount_
);
144 root
->scrollBy(scroll_amount_
);
145 EXPECT_VECTOR_EQ(root
->scrollDelta(), scroll_amount_
+ scroll_amount_
);
147 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
148 postSetNeedsCommitToMainThread();
149 } else if (impl
->activeTree()->source_frame_number() == 1) {
150 // Third or later draw after second commit.
151 EXPECT_GE(impl
->sourceAnimationFrameNumber(), 3);
152 EXPECT_VECTOR_EQ(root
->scrollDelta(), gfx::Vector2d());
154 root
->scrollOffset(),
155 initial_scroll_
+ scroll_amount_
+ scroll_amount_
);
160 virtual void applyScrollAndScale(
161 gfx::Vector2d scroll_delta
, float scale
) OVERRIDE
{
162 gfx::Vector2d offset
= m_layerTreeHost
->rootLayer()->scrollOffset();
163 m_layerTreeHost
->rootLayer()->setScrollOffset(offset
+ scroll_delta
);
167 virtual void afterTest() OVERRIDE
{
168 EXPECT_EQ(1, num_scrolls_
);
171 gfx::Vector2d initial_scroll_
;
172 gfx::Vector2d scroll_amount_
;
176 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollMultipleRedraw
)
178 class LayerTreeHostScrollTestFractionalScroll
: public LayerTreeHostScrollTest
{
180 LayerTreeHostScrollTestFractionalScroll()
181 : scroll_amount_(1.75, 0) {
184 virtual void beginTest() OVERRIDE
{
185 m_layerTreeHost
->rootLayer()->setScrollable(true);
186 postSetNeedsCommitToMainThread();
189 virtual void drawLayersOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
190 LayerImpl
* root
= impl
->rootLayer();
191 root
->setMaxScrollOffset(gfx::Vector2d(100, 100));
193 // Check that a fractional scroll delta is correctly accumulated over
195 switch (impl
->activeTree()->source_frame_number()) {
197 EXPECT_VECTOR_EQ(root
->scrollOffset(), gfx::Vector2d(0, 0));
198 EXPECT_VECTOR_EQ(root
->scrollDelta(), gfx::Vector2d(0, 0));
199 postSetNeedsCommitToMainThread();
203 root
->scrollOffset(),
204 gfx::ToFlooredVector2d(scroll_amount_
));
207 gfx::Vector2dF(fmod(scroll_amount_
.x(), 1.0f
), 0.0f
));
208 postSetNeedsCommitToMainThread();
212 root
->scrollOffset(),
213 gfx::ToFlooredVector2d(scroll_amount_
+ scroll_amount_
));
216 gfx::Vector2dF(fmod(2.0f
* scroll_amount_
.x(), 1.0f
), 0.0f
));
220 root
->scrollBy(scroll_amount_
);
223 virtual void applyScrollAndScale(
224 gfx::Vector2d scroll_delta
, float scale
) OVERRIDE
{
225 gfx::Vector2d offset
= m_layerTreeHost
->rootLayer()->scrollOffset();
226 m_layerTreeHost
->rootLayer()->setScrollOffset(offset
+ scroll_delta
);
229 virtual void afterTest() OVERRIDE
{}
232 gfx::Vector2dF scroll_amount_
;
235 TEST_F(LayerTreeHostScrollTestFractionalScroll
, runMultiThread
)
240 class LayerTreeHostScrollTestCaseWithChild
:
241 public LayerTreeHostScrollTest
,
242 public WebKit::WebLayerScrollClient
{
244 LayerTreeHostScrollTestCaseWithChild()
245 : initial_offset_(10, 20),
246 javascript_scroll_(40, 5),
247 scroll_amount_(2, -1),
251 virtual void setupTree() OVERRIDE
{
252 m_layerTreeHost
->setDeviceScaleFactor(device_scale_factor_
);
254 scoped_refptr
<Layer
> root_layer
= Layer::create();
255 root_layer
->setBounds(gfx::Size(10, 10));
257 root_scroll_layer_
= ContentLayer::create(&fake_content_layer_client_
);
258 root_scroll_layer_
->setBounds(gfx::Size(110, 110));
260 root_scroll_layer_
->setPosition(gfx::Point(0, 0));
261 root_scroll_layer_
->setAnchorPoint(gfx::PointF());
263 root_scroll_layer_
->setIsDrawable(true);
264 root_scroll_layer_
->setScrollable(true);
265 root_scroll_layer_
->setMaxScrollOffset(gfx::Vector2d(100, 100));
266 root_layer
->addChild(root_scroll_layer_
);
268 child_layer_
= ContentLayer::create(&fake_content_layer_client_
);
269 child_layer_
->setLayerScrollClient(this);
270 child_layer_
->setBounds(gfx::Size(110, 110));
272 // Scrolls on the child layer will happen at 5, 5. If they are treated
273 // like device pixels, and device scale factor is 2, then they will
274 // be considered at 2.5, 2.5 in logical pixels, and will miss this layer.
275 child_layer_
->setPosition(gfx::Point(5, 5));
276 child_layer_
->setAnchorPoint(gfx::PointF());
278 child_layer_
->setIsDrawable(true);
279 child_layer_
->setScrollable(true);
280 child_layer_
->setMaxScrollOffset(gfx::Vector2d(100, 100));
281 root_scroll_layer_
->addChild(child_layer_
);
283 if (scroll_child_layer_
) {
284 expected_scroll_layer_
= child_layer_
;
285 expected_no_scroll_layer_
= root_scroll_layer_
;
287 expected_scroll_layer_
= root_scroll_layer_
;
288 expected_no_scroll_layer_
= child_layer_
;
291 expected_scroll_layer_
->setScrollOffset(initial_offset_
);
293 m_layerTreeHost
->setRootLayer(root_layer
);
294 LayerTreeHostScrollTest::setupTree();
297 virtual void beginTest() OVERRIDE
{
298 postSetNeedsCommitToMainThread();
301 virtual void didScroll() OVERRIDE
{
302 final_scroll_offset_
= expected_scroll_layer_
->scrollOffset();
305 virtual void applyScrollAndScale(
306 gfx::Vector2d scroll_delta
, float scale
) OVERRIDE
{
307 gfx::Vector2d offset
= root_scroll_layer_
->scrollOffset();
308 root_scroll_layer_
->setScrollOffset(offset
+ scroll_delta
);
312 virtual void layout() OVERRIDE
{
314 gfx::Vector2d(), expected_no_scroll_layer_
->scrollOffset());
316 switch (m_layerTreeHost
->commitNumber()) {
320 expected_scroll_layer_
->scrollOffset());
324 initial_offset_
+ scroll_amount_
,
325 expected_scroll_layer_
->scrollOffset());
327 // Pretend like Javascript updated the scroll position itself.
328 expected_scroll_layer_
->setScrollOffset(javascript_scroll_
);
332 javascript_scroll_
+ scroll_amount_
,
333 expected_scroll_layer_
->scrollOffset());
338 virtual void commitCompleteOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
339 LayerImpl
* root_impl
= impl
->rootLayer();
340 LayerImpl
* root_scroll_layer_impl
= root_impl
->children()[0];
341 LayerImpl
* child_layer_impl
= root_scroll_layer_impl
->children()[0];
343 LayerImpl
* expected_scroll_layer_impl
= NULL
;
344 LayerImpl
* expected_no_scroll_layer_impl
= NULL
;
345 if (scroll_child_layer_
) {
346 expected_scroll_layer_impl
= child_layer_impl
;
347 expected_no_scroll_layer_impl
= root_scroll_layer_impl
;
349 expected_scroll_layer_impl
= root_scroll_layer_impl
;
350 expected_no_scroll_layer_impl
= child_layer_impl
;
353 EXPECT_VECTOR_EQ(gfx::Vector2d(), root_impl
->scrollDelta());
356 expected_no_scroll_layer_impl
->scrollDelta());
358 // Ensure device scale factor is affecting the layers.
359 gfx::Size expected_content_bounds
= gfx::ToCeiledSize(
360 gfx::ScaleSize(root_scroll_layer_impl
->bounds(), device_scale_factor_
));
362 expected_content_bounds
,
363 root_scroll_layer_
->contentBounds());
365 expected_content_bounds
= gfx::ToCeiledSize(
366 gfx::ScaleSize(child_layer_impl
->bounds(), device_scale_factor_
));
367 EXPECT_SIZE_EQ(expected_content_bounds
, child_layer_
->contentBounds());
369 switch (impl
->activeTree()->source_frame_number()) {
371 // Gesture scroll on impl thread.
372 InputHandlerClient::ScrollStatus status
= impl
->scrollBegin(
374 expected_scroll_layer_impl
->position() +
375 gfx::Vector2dF(0.5f
, 0.5f
)),
376 InputHandlerClient::Gesture
);
377 EXPECT_EQ(InputHandlerClient::ScrollStarted
, status
);
378 impl
->scrollBy(gfx::Point(), scroll_amount_
);
381 // Check the scroll is applied as a delta.
384 expected_scroll_layer_impl
->scrollOffset());
387 expected_scroll_layer_impl
->scrollDelta());
391 // Wheel scroll on impl thread.
392 InputHandlerClient::ScrollStatus status
= impl
->scrollBegin(
394 expected_scroll_layer_impl
->position() +
395 gfx::Vector2dF(0.5f
, 0.5f
)),
396 InputHandlerClient::Wheel
);
397 EXPECT_EQ(InputHandlerClient::ScrollStarted
, status
);
398 impl
->scrollBy(gfx::Point(), scroll_amount_
);
401 // Check the scroll is applied as a delta.
404 expected_scroll_layer_impl
->scrollOffset());
407 expected_scroll_layer_impl
->scrollDelta());
413 javascript_scroll_
+ scroll_amount_
,
414 expected_scroll_layer_impl
->scrollOffset());
417 expected_scroll_layer_impl
->scrollDelta());
424 virtual void afterTest() OVERRIDE
{
425 if (scroll_child_layer_
) {
426 EXPECT_EQ(0, num_scrolls_
);
428 javascript_scroll_
+ scroll_amount_
,
429 final_scroll_offset_
);
431 EXPECT_EQ(2, num_scrolls_
);
432 EXPECT_VECTOR_EQ(gfx::Vector2d(), final_scroll_offset_
);
437 float device_scale_factor_
;
438 bool scroll_child_layer_
;
440 gfx::Vector2d initial_offset_
;
441 gfx::Vector2d javascript_scroll_
;
442 gfx::Vector2d scroll_amount_
;
444 gfx::Vector2d final_scroll_offset_
;
446 FakeContentLayerClient fake_content_layer_client_
;
448 scoped_refptr
<Layer
> root_scroll_layer_
;
449 scoped_refptr
<Layer
> child_layer_
;
450 scoped_refptr
<Layer
> expected_scroll_layer_
;
451 scoped_refptr
<Layer
> expected_no_scroll_layer_
;
454 TEST_F(LayerTreeHostScrollTestCaseWithChild
, DeviceScaleFactor1_ScrollChild
) {
455 device_scale_factor_
= 1.f
;
456 scroll_child_layer_
= true;
460 TEST_F(LayerTreeHostScrollTestCaseWithChild
, DeviceScaleFactor15_ScrollChild
) {
461 device_scale_factor_
= 1.5f
;
462 scroll_child_layer_
= true;
466 TEST_F(LayerTreeHostScrollTestCaseWithChild
, DeviceScaleFactor2_ScrollChild
) {
467 device_scale_factor_
= 2.f
;
468 scroll_child_layer_
= true;
472 TEST_F(LayerTreeHostScrollTestCaseWithChild
,
473 DeviceScaleFactor1_ScrollRootScrollLayer
) {
474 device_scale_factor_
= 1.f
;
475 scroll_child_layer_
= false;
479 TEST_F(LayerTreeHostScrollTestCaseWithChild
,
480 DeviceScaleFactor15_ScrollRootScrollLayer
) {
481 device_scale_factor_
= 1.5f
;
482 scroll_child_layer_
= false;
486 TEST_F(LayerTreeHostScrollTestCaseWithChild
,
487 DeviceScaleFactor2_ScrollRootScrollLayer
) {
488 device_scale_factor_
= 2.f
;
489 scroll_child_layer_
= false;
493 class ImplSidePaintingScrollTest
: public LayerTreeHostScrollTest
{
495 virtual void initializeSettings(LayerTreeSettings
& settings
) OVERRIDE
{
496 settings
.implSidePainting
= true;
499 virtual void drawLayersOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
500 // Manual vsync tick.
501 if (impl
->pendingTree())
502 impl
->setNeedsRedraw();
506 class ImplSidePaintingScrollTestSimple
: public ImplSidePaintingScrollTest
{
508 ImplSidePaintingScrollTestSimple()
509 : initial_scroll_(10, 20),
510 main_thread_scroll_(40, 5),
511 impl_thread_scroll1_(2, -1),
512 impl_thread_scroll2_(-3, 10),
514 can_activate_(true) {
517 virtual void beginTest() OVERRIDE
{
518 m_layerTreeHost
->rootLayer()->setScrollable(true);
519 m_layerTreeHost
->rootLayer()->setScrollOffset(initial_scroll_
);
520 postSetNeedsCommitToMainThread();
523 virtual void layout() OVERRIDE
{
524 Layer
* root
= m_layerTreeHost
->rootLayer();
525 if (!m_layerTreeHost
->commitNumber())
526 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
528 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
+ impl_thread_scroll1_
);
530 // Pretend like Javascript updated the scroll position itself with a
531 // change of main_thread_scroll.
532 root
->setScrollOffset(initial_scroll_
+ main_thread_scroll_
+ impl_thread_scroll1_
);
536 virtual bool canActivatePendingTree() OVERRIDE
{
537 return can_activate_
;
540 virtual void drawLayersOnThread(LayerTreeHostImpl
* impl
) OVERRIDE
{
541 ImplSidePaintingScrollTest::drawLayersOnThread(impl
);
543 LayerImpl
* root
= impl
->rootLayer();
544 root
->setScrollable(true);
545 root
->setMaxScrollOffset(gfx::Vector2d(100, 100));
547 LayerImpl
* pending_root
=
548 impl
->activeTree()->FindPendingTreeLayerById(root
->id());
550 switch (impl
->activeTree()->source_frame_number()) {
552 if (!impl
->pendingTree()) {
553 can_activate_
= false;
554 EXPECT_VECTOR_EQ(root
->scrollDelta(), gfx::Vector2d());
555 root
->scrollBy(impl_thread_scroll1_
);
557 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
558 EXPECT_VECTOR_EQ(root
->scrollDelta(), impl_thread_scroll1_
);
559 EXPECT_VECTOR_EQ(root
->sentScrollDelta(), gfx::Vector2d());
560 postSetNeedsCommitToMainThread();
562 can_activate_
= true;
563 ASSERT_TRUE(pending_root
);
564 EXPECT_EQ(impl
->pendingTree()->source_frame_number(), 1);
566 root
->scrollBy(impl_thread_scroll2_
);
567 EXPECT_VECTOR_EQ(root
->scrollOffset(), initial_scroll_
);
568 EXPECT_VECTOR_EQ(root
->scrollDelta(),
569 impl_thread_scroll1_
+ impl_thread_scroll2_
);
570 EXPECT_VECTOR_EQ(root
->sentScrollDelta(), impl_thread_scroll1_
);
572 EXPECT_VECTOR_EQ(pending_root
->scrollOffset(),
573 initial_scroll_
+ main_thread_scroll_
+ impl_thread_scroll1_
);
574 EXPECT_VECTOR_EQ(pending_root
->scrollDelta(), impl_thread_scroll2_
);
575 EXPECT_VECTOR_EQ(pending_root
->sentScrollDelta(), gfx::Vector2d());
579 EXPECT_FALSE(impl
->pendingTree());
580 EXPECT_VECTOR_EQ(root
->scrollOffset(),
581 initial_scroll_
+ main_thread_scroll_
+ impl_thread_scroll1_
);
582 EXPECT_VECTOR_EQ(root
->scrollDelta(), impl_thread_scroll2_
);
583 EXPECT_VECTOR_EQ(root
->sentScrollDelta(), gfx::Vector2d());
589 virtual void applyScrollAndScale(
590 gfx::Vector2d scroll_delta
, float scale
) OVERRIDE
{
591 gfx::Vector2d offset
= m_layerTreeHost
->rootLayer()->scrollOffset();
592 m_layerTreeHost
->rootLayer()->setScrollOffset(offset
+ scroll_delta
);
596 virtual void afterTest() OVERRIDE
{
597 EXPECT_EQ(1, num_scrolls_
);
601 gfx::Vector2d initial_scroll_
;
602 gfx::Vector2d main_thread_scroll_
;
603 gfx::Vector2d impl_thread_scroll1_
;
604 gfx::Vector2d impl_thread_scroll2_
;
609 MULTI_THREAD_TEST_F(ImplSidePaintingScrollTestSimple
);