1// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "cc/trees/layer_tree_host.h"
6
7#include "base/memory/weak_ptr.h"
8#include "cc/layers/content_layer.h"
9#include "cc/layers/layer.h"
10#include "cc/layers/layer_impl.h"
11#include "cc/test/fake_content_layer_client.h"
12#include "cc/test/fake_layer_tree_host_client.h"
13#include "cc/test/geometry_test_utils.h"
14#include "cc/test/layer_tree_test.h"
15#include "cc/trees/layer_tree_impl.h"
16#include "ui/gfx/point_conversions.h"
17#include "ui/gfx/size_conversions.h"
18#include "ui/gfx/vector2d_conversions.h"
19
20namespace cc {
21namespace {
22
23class LayerTreeHostScrollTest : public LayerTreeTest {};
24
25class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
26 public:
27  LayerTreeHostScrollTestScrollSimple()
28      : initial_scroll_(10, 20),
29        second_scroll_(40, 5),
30        scroll_amount_(2, -1),
31        num_scrolls_(0) {}
32
33  virtual void BeginTest() OVERRIDE {
34    layer_tree_host()->root_layer()->SetScrollable(true);
35    layer_tree_host()->root_layer()
36        ->SetMaxScrollOffset(gfx::Vector2d(100, 100));
37    layer_tree_host()->root_layer()->SetScrollOffset(initial_scroll_);
38    PostSetNeedsCommitToMainThread();
39  }
40
41  virtual void Layout() OVERRIDE {
42    Layer* root = layer_tree_host()->root_layer();
43    if (!layer_tree_host()->source_frame_number()) {
44      EXPECT_VECTOR_EQ(initial_scroll_, root->scroll_offset());
45    } else {
46      EXPECT_VECTOR_EQ(initial_scroll_ + scroll_amount_, root->scroll_offset());
47
48      // Pretend like Javascript updated the scroll position itself.
49      root->SetScrollOffset(second_scroll_);
50    }
51  }
52
53  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
54    LayerImpl* root = impl->active_tree()->root_layer();
55    EXPECT_VECTOR_EQ(gfx::Vector2d(), root->ScrollDelta());
56
57    root->SetScrollable(true);
58    root->SetMaxScrollOffset(gfx::Vector2d(100, 100));
59    root->ScrollBy(scroll_amount_);
60
61    switch (impl->active_tree()->source_frame_number()) {
62      case 0:
63        EXPECT_VECTOR_EQ(initial_scroll_, root->scroll_offset());
64        EXPECT_VECTOR_EQ(scroll_amount_, root->ScrollDelta());
65        PostSetNeedsCommitToMainThread();
66        break;
67      case 1:
68        EXPECT_VECTOR_EQ(root->scroll_offset(), second_scroll_);
69        EXPECT_VECTOR_EQ(root->ScrollDelta(), scroll_amount_);
70        EndTest();
71        break;
72    }
73  }
74
75  virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
76                                   float scale) OVERRIDE {
77    num_scrolls_++;
78  }
79
80  virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, num_scrolls_); }
81
82 private:
83  gfx::Vector2d initial_scroll_;
84  gfx::Vector2d second_scroll_;
85  gfx::Vector2d scroll_amount_;
86  int num_scrolls_;
87};
88
89MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSimple);
90
91class LayerTreeHostScrollTestScrollMultipleRedraw
92    : public LayerTreeHostScrollTest {
93 public:
94  LayerTreeHostScrollTestScrollMultipleRedraw()
95      : initial_scroll_(40, 10), scroll_amount_(-3, 17), num_scrolls_(0) {}
96
97  virtual void BeginTest() OVERRIDE {
98    layer_tree_host()->root_layer()->SetScrollable(true);
99    layer_tree_host()->root_layer()->SetScrollOffset(initial_scroll_);
100    layer_tree_host()->root_layer()->SetBounds(gfx::Size(200, 200));
101    layer_tree_host()->root_layer()
102        ->SetMaxScrollOffset(gfx::Vector2d(100, 100));
103    PostSetNeedsCommitToMainThread();
104  }
105
106  virtual void BeginCommitOnThread(LayerTreeHostImpl* impl) OVERRIDE {
107    Layer* root = layer_tree_host()->root_layer();
108    switch (layer_tree_host()->source_frame_number()) {
109      case 0:
110        EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
111        break;
112      case 1:
113        EXPECT_VECTOR_EQ(root->scroll_offset(),
114                         initial_scroll_ + scroll_amount_ + scroll_amount_);
115      case 2:
116        EXPECT_VECTOR_EQ(root->scroll_offset(),
117                         initial_scroll_ + scroll_amount_ + scroll_amount_);
118        break;
119    }
120  }
121
122  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
123    LayerImpl* root = impl->active_tree()->root_layer();
124    if (impl->active_tree()->source_frame_number() == 0 &&
125        impl->SourceAnimationFrameNumber() == 1) {
126      // First draw after first commit.
127      EXPECT_VECTOR_EQ(root->ScrollDelta(), gfx::Vector2d());
128      root->ScrollBy(scroll_amount_);
129      EXPECT_VECTOR_EQ(root->ScrollDelta(), scroll_amount_);
130
131      EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
132      PostSetNeedsRedrawToMainThread();
133    } else if (impl->active_tree()->source_frame_number() == 0 &&
134               impl->SourceAnimationFrameNumber() == 2) {
135      // Second draw after first commit.
136      EXPECT_EQ(root->ScrollDelta(), scroll_amount_);
137      root->ScrollBy(scroll_amount_);
138      EXPECT_VECTOR_EQ(root->ScrollDelta(), scroll_amount_ + scroll_amount_);
139
140      EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
141      PostSetNeedsCommitToMainThread();
142    } else if (impl->active_tree()->source_frame_number() == 1) {
143      // Third or later draw after second commit.
144      EXPECT_GE(impl->SourceAnimationFrameNumber(), 3);
145      EXPECT_VECTOR_EQ(root->ScrollDelta(), gfx::Vector2d());
146      EXPECT_VECTOR_EQ(root->scroll_offset(),
147                       initial_scroll_ + scroll_amount_ + scroll_amount_);
148      EndTest();
149    }
150  }
151
152  virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
153                                   float scale) OVERRIDE {
154    num_scrolls_++;
155  }
156
157  virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, num_scrolls_); }
158
159 private:
160  gfx::Vector2d initial_scroll_;
161  gfx::Vector2d scroll_amount_;
162  int num_scrolls_;
163};
164
165MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollMultipleRedraw);
166
167class LayerTreeHostScrollTestScrollAbortedCommit
168    : public LayerTreeHostScrollTest {
169 public:
170  LayerTreeHostScrollTestScrollAbortedCommit()
171      : initial_scroll_(50, 60),
172        impl_scroll_(-3, 2),
173        second_main_scroll_(14, -3),
174        impl_scale_(2.f),
175        num_will_begin_frames_(0),
176        num_did_begin_frames_(0),
177        num_will_commits_(0),
178        num_did_commits_(0),
179        num_impl_commits_(0),
180        num_impl_scrolls_(0) {}
181
182  virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
183
184  virtual void SetupTree() OVERRIDE {
185    LayerTreeHostScrollTest::SetupTree();
186    scoped_refptr<Layer> root_scroll_layer = Layer::Create();
187    root_scroll_layer->SetScrollable(true);
188    root_scroll_layer->SetScrollOffset(initial_scroll_);
189    root_scroll_layer->SetBounds(gfx::Size(200, 200));
190    root_scroll_layer->SetMaxScrollOffset(gfx::Vector2d(100, 100));
191    root_scroll_layer->SetIsDrawable(true);
192    layer_tree_host()->root_layer()->AddChild(root_scroll_layer);
193
194    layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
195  }
196
197  virtual void WillBeginFrame() OVERRIDE {
198    num_will_begin_frames_++;
199    Layer* root_scroll_layer = layer_tree_host()->root_layer()->children()[0];
200    switch (num_will_begin_frames_) {
201      case 1:
202        // This will not be aborted because of the initial prop changes.
203        EXPECT_EQ(0, num_impl_scrolls_);
204        EXPECT_EQ(0, layer_tree_host()->source_frame_number());
205        EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(), initial_scroll_);
206        EXPECT_EQ(1.f, layer_tree_host()->page_scale_factor());
207        break;
208      case 2:
209        // This commit will be aborted, and another commit will be
210        // initiated from the redraw.
211        EXPECT_EQ(1, num_impl_scrolls_);
212        EXPECT_EQ(1, layer_tree_host()->source_frame_number());
213        EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(),
214                         initial_scroll_ + impl_scroll_);
215        EXPECT_EQ(impl_scale_, layer_tree_host()->page_scale_factor());
216        PostSetNeedsRedrawToMainThread();
217        break;
218      case 3:
219        // This commit will not be aborted because of the scroll change.
220        EXPECT_EQ(2, num_impl_scrolls_);
221        EXPECT_EQ(1, layer_tree_host()->source_frame_number());
222        EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(),
223                         initial_scroll_ + impl_scroll_ + impl_scroll_);
224        EXPECT_EQ(impl_scale_ * impl_scale_,
225                  layer_tree_host()->page_scale_factor());
226        root_scroll_layer->SetScrollOffset(root_scroll_layer->scroll_offset() +
227                                           second_main_scroll_);
228        break;
229      case 4:
230        // This commit will also be aborted.
231        EXPECT_EQ(3, num_impl_scrolls_);
232        EXPECT_EQ(2, layer_tree_host()->source_frame_number());
233        EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(),
234                         initial_scroll_ + impl_scroll_ + impl_scroll_ +
235                             impl_scroll_ + second_main_scroll_);
236        // End the test by drawing to verify this commit is also aborted.
237        PostSetNeedsRedrawToMainThread();
238        break;
239    }
240  }
241
242  virtual void DidBeginFrame() OVERRIDE { num_did_begin_frames_++; }
243
244  virtual void WillCommit() OVERRIDE { num_will_commits_++; }
245
246  virtual void DidCommit() OVERRIDE { num_did_commits_++; }
247
248  virtual void BeginCommitOnThread(LayerTreeHostImpl* impl) OVERRIDE {
249    num_impl_commits_++;
250  }
251
252  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
253    LayerImpl* root_scroll_layer =
254        impl->active_tree()->root_layer()->children()[0];
255
256    if (impl->active_tree()->source_frame_number() == 0 &&
257        impl->SourceAnimationFrameNumber() == 1) {
258      // First draw
259      EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
260      root_scroll_layer->ScrollBy(impl_scroll_);
261      EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), impl_scroll_);
262      EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(), initial_scroll_);
263
264      EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
265      EXPECT_EQ(1.f, impl->active_tree()->total_page_scale_factor());
266      impl->active_tree()->SetPageScaleDelta(impl_scale_);
267      EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
268      EXPECT_EQ(impl_scale_, impl->active_tree()->total_page_scale_factor());
269
270      // To simplify the testing flow, don't redraw here, just commit.
271      impl->SetNeedsCommit();
272    } else if (impl->active_tree()->source_frame_number() == 0 &&
273               impl->SourceAnimationFrameNumber() == 2) {
274      // Test a second draw after an aborted commit.
275      // The scroll/scale values should be baked into the offset/scale factor
276      // since the main thread consumed but aborted the begin frame.
277      EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
278      root_scroll_layer->ScrollBy(impl_scroll_);
279      EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), impl_scroll_);
280      EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(),
281                       initial_scroll_ + impl_scroll_);
282
283      EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
284      EXPECT_EQ(impl_scale_, impl->active_tree()->total_page_scale_factor());
285      impl->active_tree()->SetPageScaleDelta(impl_scale_);
286      EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
287      EXPECT_EQ(impl_scale_ * impl_scale_,
288                impl->active_tree()->total_page_scale_factor());
289
290      impl->SetNeedsCommit();
291    } else if (impl->active_tree()->source_frame_number() == 1 &&
292               impl->SourceAnimationFrameNumber() == 3) {
293      // Third draw after the second full commit.
294      EXPECT_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
295      root_scroll_layer->ScrollBy(impl_scroll_);
296      impl->SetNeedsCommit();
297      EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), impl_scroll_);
298      EXPECT_VECTOR_EQ(
299          root_scroll_layer->scroll_offset(),
300          initial_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_);
301    } else if (impl->active_tree()->source_frame_number() == 1 &&
302               impl->SourceAnimationFrameNumber() == 4) {
303      // Final draw after the second aborted commit.
304      EXPECT_VECTOR_EQ(root_scroll_layer->ScrollDelta(), gfx::Vector2d());
305      EXPECT_VECTOR_EQ(root_scroll_layer->scroll_offset(),
306                       initial_scroll_ + impl_scroll_ + impl_scroll_ +
307                           impl_scroll_ + second_main_scroll_);
308      EndTest();
309    }
310  }
311
312  virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
313                                   float scale) OVERRIDE {
314    num_impl_scrolls_++;
315  }
316
317  virtual void AfterTest() OVERRIDE {
318    EXPECT_EQ(3, num_impl_scrolls_);
319    // Verify that the embedder sees aborted commits as real commits.
320    EXPECT_EQ(4, num_will_begin_frames_);
321    EXPECT_EQ(4, num_did_begin_frames_);
322    EXPECT_EQ(4, num_will_commits_);
323    EXPECT_EQ(4, num_did_commits_);
324    // ...but the compositor thread only sees two real ones.
325    EXPECT_EQ(2, num_impl_commits_);
326  }
327
328 private:
329  gfx::Vector2d initial_scroll_;
330  gfx::Vector2d impl_scroll_;
331  gfx::Vector2d second_main_scroll_;
332  float impl_scale_;
333  int num_will_begin_frames_;
334  int num_did_begin_frames_;
335  int num_will_commits_;
336  int num_did_commits_;
337  int num_impl_commits_;
338  int num_impl_scrolls_;
339};
340
341MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollAbortedCommit);
342
343class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest {
344 public:
345  LayerTreeHostScrollTestFractionalScroll() : scroll_amount_(1.75, 0) {}
346
347  virtual void BeginTest() OVERRIDE {
348    layer_tree_host()->root_layer()->SetScrollable(true);
349    layer_tree_host()->root_layer()
350        ->SetMaxScrollOffset(gfx::Vector2d(100, 100));
351    PostSetNeedsCommitToMainThread();
352  }
353
354  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
355    LayerImpl* root = impl->active_tree()->root_layer();
356
357    // Check that a fractional scroll delta is correctly accumulated over
358    // multiple commits.
359    switch (impl->active_tree()->source_frame_number()) {
360      case 0:
361        EXPECT_VECTOR_EQ(root->scroll_offset(), gfx::Vector2d(0, 0));
362        EXPECT_VECTOR_EQ(root->ScrollDelta(), gfx::Vector2d(0, 0));
363        PostSetNeedsCommitToMainThread();
364        break;
365      case 1:
366        EXPECT_VECTOR_EQ(root->scroll_offset(),
367                         gfx::ToFlooredVector2d(scroll_amount_));
368        EXPECT_VECTOR_EQ(root->ScrollDelta(),
369                         gfx::Vector2dF(fmod(scroll_amount_.x(), 1.0f), 0.0f));
370        PostSetNeedsCommitToMainThread();
371        break;
372      case 2:
373        EXPECT_VECTOR_EQ(
374            root->scroll_offset(),
375            gfx::ToFlooredVector2d(scroll_amount_ + scroll_amount_));
376        EXPECT_VECTOR_EQ(
377            root->ScrollDelta(),
378            gfx::Vector2dF(fmod(2.0f * scroll_amount_.x(), 1.0f), 0.0f));
379        EndTest();
380        break;
381    }
382    root->ScrollBy(scroll_amount_);
383  }
384
385  virtual void AfterTest() OVERRIDE {}
386
387 private:
388  gfx::Vector2dF scroll_amount_;
389};
390
391MULTI_THREAD_TEST_F(LayerTreeHostScrollTestFractionalScroll);
392
393class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
394 public:
395  LayerTreeHostScrollTestCaseWithChild()
396      : initial_offset_(10, 20),
397        javascript_scroll_(40, 5),
398        scroll_amount_(2, -1),
399        num_scrolls_(0) {}
400
401  virtual void SetupTree() OVERRIDE {
402    layer_tree_host()->SetDeviceScaleFactor(device_scale_factor_);
403
404    scoped_refptr<Layer> root_layer = Layer::Create();
405    root_layer->SetBounds(gfx::Size(10, 10));
406
407    root_scroll_layer_ = ContentLayer::Create(&fake_content_layer_client_);
408    root_scroll_layer_->SetBounds(gfx::Size(110, 110));
409
410    root_scroll_layer_->SetPosition(gfx::Point());
411    root_scroll_layer_->SetAnchorPoint(gfx::PointF());
412
413    root_scroll_layer_->SetIsDrawable(true);
414    root_scroll_layer_->SetScrollable(true);
415    root_scroll_layer_->SetMaxScrollOffset(gfx::Vector2d(100, 100));
416    root_layer->AddChild(root_scroll_layer_);
417
418    child_layer_ = ContentLayer::Create(&fake_content_layer_client_);
419    child_layer_->set_did_scroll_callback(
420        base::Bind(&LayerTreeHostScrollTestCaseWithChild::DidScroll,
421                   base::Unretained(this)));
422    child_layer_->SetBounds(gfx::Size(110, 110));
423
424    if (scroll_child_layer_) {
425      // Scrolls on the child layer will happen at 5, 5. If they are treated
426      // like device pixels, and device scale factor is 2, then they will
427      // be considered at 2.5, 2.5 in logical pixels, and will miss this layer.
428      child_layer_->SetPosition(gfx::Point(5, 5));
429    } else {
430      // Adjust the child layer horizontally so that scrolls will never hit it.
431      child_layer_->SetPosition(gfx::Point(60, 5));
432    }
433    child_layer_->SetAnchorPoint(gfx::PointF());
434
435    child_layer_->SetIsDrawable(true);
436    child_layer_->SetScrollable(true);
437    child_layer_->SetMaxScrollOffset(gfx::Vector2d(100, 100));
438    root_scroll_layer_->AddChild(child_layer_);
439
440    if (scroll_child_layer_) {
441      expected_scroll_layer_ = child_layer_;
442      expected_no_scroll_layer_ = root_scroll_layer_;
443    } else {
444      expected_scroll_layer_ = root_scroll_layer_;
445      expected_no_scroll_layer_ = child_layer_;
446    }
447
448    expected_scroll_layer_->SetScrollOffset(initial_offset_);
449
450    layer_tree_host()->SetRootLayer(root_layer);
451    LayerTreeHostScrollTest::SetupTree();
452  }
453
454  virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
455
456  virtual void WillCommit() OVERRIDE {
457    // Keep the test committing (otherwise the early out for no update
458    // will stall the test).
459    if (layer_tree_host()->source_frame_number() < 2) {
460      layer_tree_host()->SetNeedsCommit();
461    }
462  }
463
464  void DidScroll() {
465    final_scroll_offset_ = expected_scroll_layer_->scroll_offset();
466  }
467
468  virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
469                                   float scale) OVERRIDE {
470    num_scrolls_++;
471  }
472
473  virtual void Layout() OVERRIDE {
474    EXPECT_VECTOR_EQ(gfx::Vector2d(),
475                     expected_no_scroll_layer_->scroll_offset());
476
477    switch (layer_tree_host()->source_frame_number()) {
478      case 0:
479        EXPECT_VECTOR_EQ(initial_offset_,
480                         expected_scroll_layer_->scroll_offset());
481        break;
482      case 1:
483        EXPECT_VECTOR_EQ(initial_offset_ + scroll_amount_,
484                         expected_scroll_layer_->scroll_offset());
485
486        // Pretend like Javascript updated the scroll position itself.
487        expected_scroll_layer_->SetScrollOffset(javascript_scroll_);
488        break;
489      case 2:
490        EXPECT_VECTOR_EQ(javascript_scroll_ + scroll_amount_,
491                         expected_scroll_layer_->scroll_offset());
492        break;
493    }
494  }
495
496  virtual void DidActivateTreeOnThread(LayerTreeHostImpl* impl) OVERRIDE {
497    LayerImpl* root_impl = impl->active_tree()->root_layer();
498    LayerImpl* root_scroll_layer_impl = root_impl->children()[0];
499    LayerImpl* child_layer_impl = root_scroll_layer_impl->children()[0];
500
501    LayerImpl* expected_scroll_layer_impl = NULL;
502    LayerImpl* expected_no_scroll_layer_impl = NULL;
503    if (scroll_child_layer_) {
504      expected_scroll_layer_impl = child_layer_impl;
505      expected_no_scroll_layer_impl = root_scroll_layer_impl;
506    } else {
507      expected_scroll_layer_impl = root_scroll_layer_impl;
508      expected_no_scroll_layer_impl = child_layer_impl;
509    }
510
511    EXPECT_VECTOR_EQ(gfx::Vector2d(), root_impl->ScrollDelta());
512    EXPECT_VECTOR_EQ(gfx::Vector2d(),
513                     expected_no_scroll_layer_impl->ScrollDelta());
514
515    // Ensure device scale factor is affecting the layers.
516    gfx::Size expected_content_bounds = gfx::ToCeiledSize(
517        gfx::ScaleSize(root_scroll_layer_impl->bounds(), device_scale_factor_));
518    EXPECT_SIZE_EQ(expected_content_bounds,
519                   root_scroll_layer_->content_bounds());
520
521    expected_content_bounds = gfx::ToCeiledSize(
522        gfx::ScaleSize(child_layer_impl->bounds(), device_scale_factor_));
523    EXPECT_SIZE_EQ(expected_content_bounds, child_layer_->content_bounds());
524
525    switch (impl->active_tree()->source_frame_number()) {
526      case 0: {
527        // Gesture scroll on impl thread.
528        InputHandler::ScrollStatus status = impl->ScrollBegin(
529            gfx::ToCeiledPoint(expected_scroll_layer_impl->position() -
530                               gfx::Vector2dF(0.5f, 0.5f)),
531            InputHandler::Gesture);
532        EXPECT_EQ(InputHandler::ScrollStarted, status);
533        impl->ScrollBy(gfx::Point(), scroll_amount_);
534        impl->ScrollEnd();
535
536        // Check the scroll is applied as a delta.
537        EXPECT_VECTOR_EQ(initial_offset_,
538                         expected_scroll_layer_impl->scroll_offset());
539        EXPECT_VECTOR_EQ(scroll_amount_,
540                         expected_scroll_layer_impl->ScrollDelta());
541        break;
542      }
543      case 1: {
544        // Wheel scroll on impl thread.
545        InputHandler::ScrollStatus status = impl->ScrollBegin(
546            gfx::ToCeiledPoint(expected_scroll_layer_impl->position() +
547                               gfx::Vector2dF(0.5f, 0.5f)),
548            InputHandler::Wheel);
549        EXPECT_EQ(InputHandler::ScrollStarted, status);
550        impl->ScrollBy(gfx::Point(), scroll_amount_);
551        impl->ScrollEnd();
552
553        // Check the scroll is applied as a delta.
554        EXPECT_VECTOR_EQ(javascript_scroll_,
555                         expected_scroll_layer_impl->scroll_offset());
556        EXPECT_VECTOR_EQ(scroll_amount_,
557                         expected_scroll_layer_impl->ScrollDelta());
558        break;
559      }
560      case 2:
561
562        EXPECT_VECTOR_EQ(javascript_scroll_ + scroll_amount_,
563                         expected_scroll_layer_impl->scroll_offset());
564        EXPECT_VECTOR_EQ(gfx::Vector2d(),
565                         expected_scroll_layer_impl->ScrollDelta());
566
567        EndTest();
568        break;
569    }
570  }
571
572  virtual void AfterTest() OVERRIDE {
573    if (scroll_child_layer_) {
574      EXPECT_EQ(0, num_scrolls_);
575      EXPECT_VECTOR_EQ(javascript_scroll_ + scroll_amount_,
576                       final_scroll_offset_);
577    } else {
578      EXPECT_EQ(2, num_scrolls_);
579      EXPECT_VECTOR_EQ(gfx::Vector2d(), final_scroll_offset_);
580    }
581  }
582
583 protected:
584  float device_scale_factor_;
585  bool scroll_child_layer_;
586
587  gfx::Vector2d initial_offset_;
588  gfx::Vector2d javascript_scroll_;
589  gfx::Vector2d scroll_amount_;
590  int num_scrolls_;
591  gfx::Vector2d final_scroll_offset_;
592
593  FakeContentLayerClient fake_content_layer_client_;
594
595  scoped_refptr<Layer> root_scroll_layer_;
596  scoped_refptr<Layer> child_layer_;
597  scoped_refptr<Layer> expected_scroll_layer_;
598  scoped_refptr<Layer> expected_no_scroll_layer_;
599};
600
601TEST_F(LayerTreeHostScrollTestCaseWithChild,
602       DeviceScaleFactor1_ScrollChild_DirectRenderer_MainThreadPaint) {
603  device_scale_factor_ = 1.f;
604  scroll_child_layer_ = true;
605  RunTest(true, false, false);
606}
607
608TEST_F(LayerTreeHostScrollTestCaseWithChild,
609       DeviceScaleFactor1_ScrollChild_DirectRenderer_ImplSidePaint) {
610  device_scale_factor_ = 1.f;
611  scroll_child_layer_ = true;
612  RunTest(true, false, true);
613}
614
615TEST_F(LayerTreeHostScrollTestCaseWithChild,
616       DeviceScaleFactor1_ScrollChild_DelegatingRenderer_MainThreadPaint) {
617  device_scale_factor_ = 1.f;
618  scroll_child_layer_ = true;
619  RunTest(true, true, false);
620}
621
622TEST_F(LayerTreeHostScrollTestCaseWithChild,
623       DeviceScaleFactor1_ScrollChild_DelegatingRenderer_ImplSidePaint) {
624  device_scale_factor_ = 1.f;
625  scroll_child_layer_ = true;
626  RunTest(true, true, true);
627}
628
629TEST_F(LayerTreeHostScrollTestCaseWithChild,
630       DeviceScaleFactor15_ScrollChild_DirectRenderer) {
631  device_scale_factor_ = 1.5f;
632  scroll_child_layer_ = true;
633  RunTest(true, false, true);
634}
635
636TEST_F(LayerTreeHostScrollTestCaseWithChild,
637       DeviceScaleFactor15_ScrollChild_DelegatingRenderer) {
638  device_scale_factor_ = 1.5f;
639  scroll_child_layer_ = true;
640  RunTest(true, true, true);
641}
642
643TEST_F(LayerTreeHostScrollTestCaseWithChild,
644       DeviceScaleFactor2_ScrollChild_DirectRenderer) {
645  device_scale_factor_ = 2.f;
646  scroll_child_layer_ = true;
647  RunTest(true, false, true);
648}
649
650TEST_F(LayerTreeHostScrollTestCaseWithChild,
651       DeviceScaleFactor2_ScrollChild_DelegatingRenderer) {
652  device_scale_factor_ = 2.f;
653  scroll_child_layer_ = true;
654  RunTest(true, true, true);
655}
656
657TEST_F(LayerTreeHostScrollTestCaseWithChild,
658       DeviceScaleFactor1_ScrollRootScrollLayer_DirectRenderer) {
659  device_scale_factor_ = 1.f;
660  scroll_child_layer_ = false;
661  RunTest(true, false, true);
662}
663
664TEST_F(LayerTreeHostScrollTestCaseWithChild,
665       DeviceScaleFactor1_ScrollRootScrollLayer_DelegatingRenderer) {
666  device_scale_factor_ = 1.f;
667  scroll_child_layer_ = false;
668  RunTest(true, true, true);
669}
670
671TEST_F(LayerTreeHostScrollTestCaseWithChild,
672       DeviceScaleFactor15_ScrollRootScrollLayer_DirectRenderer) {
673  device_scale_factor_ = 1.5f;
674  scroll_child_layer_ = false;
675  RunTest(true, false, true);
676}
677
678TEST_F(LayerTreeHostScrollTestCaseWithChild,
679       DeviceScaleFactor15_ScrollRootScrollLayer_DelegatingRenderer) {
680  device_scale_factor_ = 1.5f;
681  scroll_child_layer_ = false;
682  RunTest(true, true, true);
683}
684
685TEST_F(LayerTreeHostScrollTestCaseWithChild,
686       DeviceScaleFactor2_ScrollRootScrollLayer_DirectRenderer_MainSidePaint) {
687  device_scale_factor_ = 2.f;
688  scroll_child_layer_ = false;
689  RunTest(true, false, false);
690}
691
692TEST_F(LayerTreeHostScrollTestCaseWithChild,
693       DeviceScaleFactor2_ScrollRootScrollLayer_DirectRenderer_ImplSidePaint) {
694  device_scale_factor_ = 2.f;
695  scroll_child_layer_ = false;
696  RunTest(true, false, true);
697}
698
699TEST_F(LayerTreeHostScrollTestCaseWithChild,
700       DeviceScaleFactor2_ScrollRootScrollLayer_DelegatingRenderer) {
701  device_scale_factor_ = 2.f;
702  scroll_child_layer_ = false;
703  RunTest(true, true, true);
704}
705
706class ImplSidePaintingScrollTest : public LayerTreeHostScrollTest {
707 public:
708  virtual void InitializeSettings(LayerTreeSettings* settings) OVERRIDE {
709    settings->impl_side_painting = true;
710  }
711
712  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
713    if (impl->pending_tree())
714      impl->SetNeedsRedraw();
715  }
716};
717
718class ImplSidePaintingScrollTestSimple : public ImplSidePaintingScrollTest {
719 public:
720  ImplSidePaintingScrollTestSimple()
721      : initial_scroll_(10, 20),
722        main_thread_scroll_(40, 5),
723        impl_thread_scroll1_(2, -1),
724        impl_thread_scroll2_(-3, 10),
725        num_scrolls_(0),
726        can_activate_(true) {}
727
728  virtual void BeginTest() OVERRIDE {
729    layer_tree_host()->root_layer()->SetScrollable(true);
730    layer_tree_host()->root_layer()
731        ->SetMaxScrollOffset(gfx::Vector2d(100, 100));
732    layer_tree_host()->root_layer()->SetScrollOffset(initial_scroll_);
733    PostSetNeedsCommitToMainThread();
734  }
735
736  virtual void Layout() OVERRIDE {
737    Layer* root = layer_tree_host()->root_layer();
738    if (!layer_tree_host()->source_frame_number()) {
739      EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
740    } else {
741      EXPECT_VECTOR_EQ(root->scroll_offset(),
742                       initial_scroll_ + impl_thread_scroll1_);
743
744      // Pretend like Javascript updated the scroll position itself with a
745      // change of main_thread_scroll.
746      root->SetScrollOffset(initial_scroll_ + main_thread_scroll_ +
747                            impl_thread_scroll1_);
748    }
749  }
750
751  virtual bool CanActivatePendingTree(LayerTreeHostImpl* impl) OVERRIDE {
752    return can_activate_;
753  }
754
755  virtual bool CanActivatePendingTreeIfNeeded(LayerTreeHostImpl* impl)
756      OVERRIDE {
757    return can_activate_;
758  }
759
760  virtual void CommitCompleteOnThread(LayerTreeHostImpl* impl) OVERRIDE {
761    // We force a second draw here of the first commit before activating
762    // the second commit.
763    if (impl->active_tree()->source_frame_number() == 0)
764      impl->SetNeedsRedraw();
765  }
766
767  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
768    ImplSidePaintingScrollTest::DrawLayersOnThread(impl);
769
770    LayerImpl* root = impl->active_tree()->root_layer();
771    LayerImpl* pending_root =
772        impl->active_tree()->FindPendingTreeLayerById(root->id());
773
774    switch (impl->active_tree()->source_frame_number()) {
775      case 0:
776        if (!impl->pending_tree()) {
777          can_activate_ = false;
778          EXPECT_VECTOR_EQ(root->ScrollDelta(), gfx::Vector2d());
779          root->ScrollBy(impl_thread_scroll1_);
780
781          EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
782          EXPECT_VECTOR_EQ(root->ScrollDelta(), impl_thread_scroll1_);
783          EXPECT_VECTOR_EQ(root->sent_scroll_delta(), gfx::Vector2d());
784          PostSetNeedsCommitToMainThread();
785
786          // CommitCompleteOnThread will trigger this function again
787          // and cause us to take the else clause.
788        } else {
789          can_activate_ = true;
790          ASSERT_TRUE(pending_root);
791          EXPECT_EQ(impl->pending_tree()->source_frame_number(), 1);
792
793          root->ScrollBy(impl_thread_scroll2_);
794          EXPECT_VECTOR_EQ(root->scroll_offset(), initial_scroll_);
795          EXPECT_VECTOR_EQ(root->ScrollDelta(),
796                           impl_thread_scroll1_ + impl_thread_scroll2_);
797          EXPECT_VECTOR_EQ(root->sent_scroll_delta(), impl_thread_scroll1_);
798
799          EXPECT_VECTOR_EQ(
800              pending_root->scroll_offset(),
801              initial_scroll_ + main_thread_scroll_ + impl_thread_scroll1_);
802          EXPECT_VECTOR_EQ(pending_root->ScrollDelta(), impl_thread_scroll2_);
803          EXPECT_VECTOR_EQ(pending_root->sent_scroll_delta(), gfx::Vector2d());
804        }
805        break;
806      case 1:
807        EXPECT_FALSE(impl->pending_tree());
808        EXPECT_VECTOR_EQ(
809            root->scroll_offset(),
810            initial_scroll_ + main_thread_scroll_ + impl_thread_scroll1_);
811        EXPECT_VECTOR_EQ(root->ScrollDelta(), impl_thread_scroll2_);
812        EXPECT_VECTOR_EQ(root->sent_scroll_delta(), gfx::Vector2d());
813        EndTest();
814        break;
815    }
816  }
817
818  virtual void ApplyScrollAndScale(gfx::Vector2d scroll_delta,
819                                   float scale) OVERRIDE {
820    num_scrolls_++;
821  }
822
823  virtual void AfterTest() OVERRIDE { EXPECT_EQ(1, num_scrolls_); }
824
825 private:
826  gfx::Vector2d initial_scroll_;
827  gfx::Vector2d main_thread_scroll_;
828  gfx::Vector2d impl_thread_scroll1_;
829  gfx::Vector2d impl_thread_scroll2_;
830  int num_scrolls_;
831  bool can_activate_;
832};
833
834MULTI_THREAD_TEST_F(ImplSidePaintingScrollTestSimple);
835
836class LayerTreeHostScrollTestScrollZeroMaxScrollOffset
837    : public LayerTreeHostScrollTest {
838 public:
839  LayerTreeHostScrollTestScrollZeroMaxScrollOffset() {}
840
841  virtual void BeginTest() OVERRIDE { PostSetNeedsCommitToMainThread(); }
842
843  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
844    LayerImpl* root = impl->active_tree()->root_layer();
845    root->SetScrollable(true);
846
847    root->SetMaxScrollOffset(gfx::Vector2d(100, 100));
848    EXPECT_EQ(InputHandler::ScrollStarted,
849              root->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture));
850
851    root->SetMaxScrollOffset(gfx::Vector2d(0, 0));
852    EXPECT_EQ(InputHandler::ScrollIgnored,
853              root->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture));
854
855    root->SetMaxScrollOffset(gfx::Vector2d(-100, -100));
856    EXPECT_EQ(InputHandler::ScrollIgnored,
857              root->TryScroll(gfx::PointF(0.0f, 1.0f), InputHandler::Gesture));
858
859    EndTest();
860  }
861
862  virtual void AfterTest() OVERRIDE {}
863};
864
865SINGLE_AND_MULTI_THREAD_TEST_F(
866    LayerTreeHostScrollTestScrollZeroMaxScrollOffset);
867
868class ThreadCheckingInputHandlerClient : public InputHandlerClient {
869 public:
870  ThreadCheckingInputHandlerClient(base::SingleThreadTaskRunner* runner,
871                                   bool* received_stop_flinging)
872      : task_runner_(runner), received_stop_flinging_(received_stop_flinging) {}
873
874  virtual void WillShutdown() OVERRIDE {
875    if (!received_stop_flinging_)
876      ADD_FAILURE() << "WillShutdown() called before fling stopped";
877  }
878
879  virtual void Animate(base::TimeTicks time) OVERRIDE {
880    if (!task_runner_->BelongsToCurrentThread())
881      ADD_FAILURE() << "Animate called on wrong thread";
882  }
883
884  virtual void MainThreadHasStoppedFlinging() OVERRIDE {
885    if (!task_runner_->BelongsToCurrentThread())
886      ADD_FAILURE() << "MainThreadHasStoppedFlinging called on wrong thread";
887    *received_stop_flinging_ = true;
888  }
889
890  virtual void DidOverscroll(const DidOverscrollParams& params) OVERRIDE {
891    if (!task_runner_->BelongsToCurrentThread())
892      ADD_FAILURE() << "DidOverscroll called on wrong thread";
893  }
894
895 private:
896  base::SingleThreadTaskRunner* task_runner_;
897  bool* received_stop_flinging_;
898};
899
900void BindInputHandlerOnCompositorThread(
901    const base::WeakPtr<InputHandler>& input_handler,
902    ThreadCheckingInputHandlerClient* client) {
903  input_handler->BindToClient(client);
904}
905
906TEST(LayerTreeHostFlingTest, DidStopFlingingThread) {
907  base::Thread impl_thread("cc");
908  ASSERT_TRUE(impl_thread.Start());
909
910  bool received_stop_flinging = false;
911  LayerTreeSettings settings;
912
913  ThreadCheckingInputHandlerClient input_handler_client(
914          impl_thread.message_loop_proxy().get(), &received_stop_flinging);
915  FakeLayerTreeHostClient client(FakeLayerTreeHostClient::DIRECT_3D);
916
917  ASSERT_TRUE(impl_thread.message_loop_proxy().get());
918  scoped_ptr<LayerTreeHost> layer_tree_host = LayerTreeHost::Create(
919      &client, settings, impl_thread.message_loop_proxy());
920
921  impl_thread.message_loop_proxy()
922      ->PostTask(FROM_HERE,
923                 base::Bind(&BindInputHandlerOnCompositorThread,
924                            layer_tree_host->GetInputHandler(),
925                            base::Unretained(&input_handler_client)));
926
927  layer_tree_host->DidStopFlinging();
928  layer_tree_host.reset();
929  impl_thread.Stop();
930  EXPECT_TRUE(received_stop_flinging);
931}
932
933class LayerTreeHostScrollTestLayerStructureChange
934    : public LayerTreeHostScrollTest {
935 public:
936  LayerTreeHostScrollTestLayerStructureChange()
937      : scroll_destroy_whole_tree_(false) {}
938
939  virtual void SetupTree() OVERRIDE {
940    scoped_refptr<Layer> root_layer = Layer::Create();
941    root_layer->SetBounds(gfx::Size(10, 10));
942
943    Layer* root_scroll_layer =
944        CreateScrollLayer(root_layer.get(), &root_scroll_layer_client_);
945    CreateScrollLayer(root_layer.get(), &sibling_scroll_layer_client_);
946    CreateScrollLayer(root_scroll_layer, &child_scroll_layer_client_);
947
948    layer_tree_host()->SetRootLayer(root_layer);
949    LayerTreeHostScrollTest::SetupTree();
950  }
951
952  virtual void BeginTest() OVERRIDE {
953    PostSetNeedsCommitToMainThread();
954  }
955
956  virtual void DrawLayersOnThread(LayerTreeHostImpl* impl) OVERRIDE {
957    LayerImpl* root = impl->active_tree()->root_layer();
958    switch (impl->active_tree()->source_frame_number()) {
959      case 0:
960        root->child_at(0)->SetScrollDelta(gfx::Vector2dF(5, 5));
961        root->child_at(0)->child_at(0)->SetScrollDelta(gfx::Vector2dF(5, 5));
962        root->child_at(1)->SetScrollDelta(gfx::Vector2dF(5, 5));
963        PostSetNeedsCommitToMainThread();
964        break;
965      case 1:
966        EndTest();
967        break;
968    }
969  }
970
971  virtual void AfterTest() OVERRIDE {}
972
973  virtual void DidScroll(Layer* layer) {
974    if (scroll_destroy_whole_tree_) {
975      layer_tree_host()->SetRootLayer(NULL);
976      EndTest();
977      return;
978    }
979    layer->RemoveFromParent();
980  }
981
982 protected:
983  class FakeLayerScrollClient {
984   public:
985    void DidScroll() {
986      owner_->DidScroll(layer_);
987    }
988    LayerTreeHostScrollTestLayerStructureChange* owner_;
989    Layer* layer_;
990  };
991
992  Layer* CreateScrollLayer(Layer* parent, FakeLayerScrollClient* client) {
993    scoped_refptr<Layer> scroll_layer =
994        ContentLayer::Create(&fake_content_layer_client_);
995    scroll_layer->SetBounds(gfx::Size(110, 110));
996    scroll_layer->SetPosition(gfx::Point(0, 0));
997    scroll_layer->SetAnchorPoint(gfx::PointF());
998    scroll_layer->SetIsDrawable(true);
999    scroll_layer->SetScrollable(true);
1000    scroll_layer->SetMaxScrollOffset(gfx::Vector2d(100, 100));
1001    scroll_layer->set_did_scroll_callback(base::Bind(
1002        &FakeLayerScrollClient::DidScroll, base::Unretained(client)));
1003    client->owner_ = this;
1004    client->layer_ = scroll_layer.get();
1005    parent->AddChild(scroll_layer);
1006    return scroll_layer.get();
1007  }
1008
1009  FakeLayerScrollClient root_scroll_layer_client_;
1010  FakeLayerScrollClient sibling_scroll_layer_client_;
1011  FakeLayerScrollClient child_scroll_layer_client_;
1012
1013  FakeContentLayerClient fake_content_layer_client_;
1014
1015  bool scroll_destroy_whole_tree_;
1016};
1017
1018TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyLayer) {
1019    RunTest(true, false, false);
1020}
1021
1022TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyWholeTree) {
1023    scroll_destroy_whole_tree_ = true;
1024    RunTest(true, false, false);
1025}
1026
1027}  // namespace
1028}  // namespace cc
1029