WebKit Roll 139512:139548
[chromium-blink-merge.git] / cc / layer_tree_host_unittest_scroll.cc
blob5c30a22de8b5405d1d71ab8b25c4ca2574c72032
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"
8 #include "cc/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"
19 namespace cc {
20 namespace {
22 class LayerTreeHostScrollTest : public ThreadedTest {};
24 class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
25 public:
26 LayerTreeHostScrollTestScrollSimple()
27 : initial_scroll_(10, 20),
28 second_scroll_(40, 5),
29 scroll_amount_(2, -1),
30 num_scrolls_(0) {
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_);
43 else {
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()) {
60 case 0:
61 EXPECT_VECTOR_EQ(root->scrollOffset(), initial_scroll_);
62 EXPECT_VECTOR_EQ(root->scrollDelta(), scroll_amount_);
63 postSetNeedsCommitToMainThread();
64 break;
65 case 1:
66 EXPECT_VECTOR_EQ(root->scrollOffset(), second_scroll_);
67 EXPECT_VECTOR_EQ(root->scrollDelta(), scroll_amount_);
68 endTest();
69 break;
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);
77 num_scrolls_++;
80 virtual void afterTest() OVERRIDE {
81 EXPECT_EQ(1, num_scrolls_);
84 private:
85 gfx::Vector2d initial_scroll_;
86 gfx::Vector2d second_scroll_;
87 gfx::Vector2d scroll_amount_;
88 int num_scrolls_;
91 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSimple)
93 class LayerTreeHostScrollTestScrollMultipleRedraw :
94 public LayerTreeHostScrollTest {
95 public:
96 LayerTreeHostScrollTestScrollMultipleRedraw()
97 : initial_scroll_(40, 10),
98 scroll_amount_(-3, 17),
99 num_scrolls_(0) {
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()) {
111 case 0:
112 EXPECT_VECTOR_EQ(root->scrollOffset(), initial_scroll_);
113 break;
114 case 1:
115 EXPECT_VECTOR_EQ(
116 root->scrollOffset(),
117 initial_scroll_ + scroll_amount_ + scroll_amount_);
118 case 2:
119 EXPECT_VECTOR_EQ(
120 root->scrollOffset(),
121 initial_scroll_ + scroll_amount_ + scroll_amount_);
122 break;
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());
153 EXPECT_VECTOR_EQ(
154 root->scrollOffset(),
155 initial_scroll_ + scroll_amount_ + scroll_amount_);
156 endTest();
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);
164 num_scrolls_++;
167 virtual void afterTest() OVERRIDE {
168 EXPECT_EQ(1, num_scrolls_);
170 private:
171 gfx::Vector2d initial_scroll_;
172 gfx::Vector2d scroll_amount_;
173 int num_scrolls_;
176 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollMultipleRedraw)
178 class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest {
179 public:
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
194 // multiple commits.
195 switch (impl->activeTree()->source_frame_number()) {
196 case 0:
197 EXPECT_VECTOR_EQ(root->scrollOffset(), gfx::Vector2d(0, 0));
198 EXPECT_VECTOR_EQ(root->scrollDelta(), gfx::Vector2d(0, 0));
199 postSetNeedsCommitToMainThread();
200 break;
201 case 1:
202 EXPECT_VECTOR_EQ(
203 root->scrollOffset(),
204 gfx::ToFlooredVector2d(scroll_amount_));
205 EXPECT_VECTOR_EQ(
206 root->scrollDelta(),
207 gfx::Vector2dF(fmod(scroll_amount_.x(), 1.0f), 0.0f));
208 postSetNeedsCommitToMainThread();
209 break;
210 case 2:
211 EXPECT_VECTOR_EQ(
212 root->scrollOffset(),
213 gfx::ToFlooredVector2d(scroll_amount_ + scroll_amount_));
214 EXPECT_VECTOR_EQ(
215 root->scrollDelta(),
216 gfx::Vector2dF(fmod(2.0f * scroll_amount_.x(), 1.0f), 0.0f));
217 endTest();
218 break;
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 {}
231 private:
232 gfx::Vector2dF scroll_amount_;
235 TEST_F(LayerTreeHostScrollTestFractionalScroll, runMultiThread)
237 runTest(true);
240 class LayerTreeHostScrollTestCaseWithChild :
241 public LayerTreeHostScrollTest,
242 public WebKit::WebLayerScrollClient {
243 public:
244 LayerTreeHostScrollTestCaseWithChild()
245 : initial_offset_(10, 20),
246 javascript_scroll_(40, 5),
247 scroll_amount_(2, -1),
248 num_scrolls_(0) {
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_;
286 } else {
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);
309 num_scrolls_++;
312 virtual void layout() OVERRIDE {
313 EXPECT_VECTOR_EQ(
314 gfx::Vector2d(), expected_no_scroll_layer_->scrollOffset());
316 switch (m_layerTreeHost->commitNumber()) {
317 case 0:
318 EXPECT_VECTOR_EQ(
319 initial_offset_,
320 expected_scroll_layer_->scrollOffset());
321 break;
322 case 1:
323 EXPECT_VECTOR_EQ(
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_);
329 break;
330 case 2:
331 EXPECT_VECTOR_EQ(
332 javascript_scroll_ + scroll_amount_,
333 expected_scroll_layer_->scrollOffset());
334 break;
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;
348 } else {
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());
354 EXPECT_VECTOR_EQ(
355 gfx::Vector2d(),
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_));
361 EXPECT_SIZE_EQ(
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()) {
370 case 0: {
371 // Gesture scroll on impl thread.
372 InputHandlerClient::ScrollStatus status = impl->scrollBegin(
373 gfx::ToCeiledPoint(
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_);
379 impl->scrollEnd();
381 // Check the scroll is applied as a delta.
382 EXPECT_VECTOR_EQ(
383 initial_offset_,
384 expected_scroll_layer_impl->scrollOffset());
385 EXPECT_VECTOR_EQ(
386 scroll_amount_,
387 expected_scroll_layer_impl->scrollDelta());
388 break;
390 case 1: {
391 // Wheel scroll on impl thread.
392 InputHandlerClient::ScrollStatus status = impl->scrollBegin(
393 gfx::ToCeiledPoint(
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_);
399 impl->scrollEnd();
401 // Check the scroll is applied as a delta.
402 EXPECT_VECTOR_EQ(
403 javascript_scroll_,
404 expected_scroll_layer_impl->scrollOffset());
405 EXPECT_VECTOR_EQ(
406 scroll_amount_,
407 expected_scroll_layer_impl->scrollDelta());
408 break;
410 case 2:
412 EXPECT_VECTOR_EQ(
413 javascript_scroll_ + scroll_amount_,
414 expected_scroll_layer_impl->scrollOffset());
415 EXPECT_VECTOR_EQ(
416 gfx::Vector2d(),
417 expected_scroll_layer_impl->scrollDelta());
419 endTest();
420 break;
424 virtual void afterTest() OVERRIDE {
425 if (scroll_child_layer_) {
426 EXPECT_EQ(0, num_scrolls_);
427 EXPECT_VECTOR_EQ(
428 javascript_scroll_ + scroll_amount_,
429 final_scroll_offset_);
430 } else {
431 EXPECT_EQ(2, num_scrolls_);
432 EXPECT_VECTOR_EQ(gfx::Vector2d(), final_scroll_offset_);
436 protected:
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_;
443 int num_scrolls_;
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;
457 runTest(true);
460 TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor15_ScrollChild) {
461 device_scale_factor_ = 1.5f;
462 scroll_child_layer_ = true;
463 runTest(true);
466 TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor2_ScrollChild) {
467 device_scale_factor_ = 2.f;
468 scroll_child_layer_ = true;
469 runTest(true);
472 TEST_F(LayerTreeHostScrollTestCaseWithChild,
473 DeviceScaleFactor1_ScrollRootScrollLayer) {
474 device_scale_factor_ = 1.f;
475 scroll_child_layer_ = false;
476 runTest(true);
479 TEST_F(LayerTreeHostScrollTestCaseWithChild,
480 DeviceScaleFactor15_ScrollRootScrollLayer) {
481 device_scale_factor_ = 1.5f;
482 scroll_child_layer_ = false;
483 runTest(true);
486 TEST_F(LayerTreeHostScrollTestCaseWithChild,
487 DeviceScaleFactor2_ScrollRootScrollLayer) {
488 device_scale_factor_ = 2.f;
489 scroll_child_layer_ = false;
490 runTest(true);
493 class ImplSidePaintingScrollTest : public LayerTreeHostScrollTest {
494 public:
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 {
507 public:
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),
513 num_scrolls_(0),
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_);
527 else {
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()) {
551 case 0:
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();
561 } else {
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());
577 break;
578 case 1:
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());
584 endTest();
585 break;
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);
593 num_scrolls_++;
596 virtual void afterTest() OVERRIDE {
597 EXPECT_EQ(1, num_scrolls_);
600 private:
601 gfx::Vector2d initial_scroll_;
602 gfx::Vector2d main_thread_scroll_;
603 gfx::Vector2d impl_thread_scroll1_;
604 gfx::Vector2d impl_thread_scroll2_;
605 int num_scrolls_;
606 bool can_activate_;
609 MULTI_THREAD_TEST_F(ImplSidePaintingScrollTestSimple);
611 } // namespace
612 } // namespace cc