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/bind.h"
8 #include "base/location.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/single_thread_task_runner.h"
11 #include "base/stl_util.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 #include "cc/animation/animation_host.h"
14 #include "cc/base/completion_event.h"
15 #include "cc/input/main_thread_scrolling_reason.h"
16 #include "cc/input/scroll_elasticity_helper.h"
17 #include "cc/input/scroll_input_type.h"
18 #include "cc/layers/layer.h"
19 #include "cc/layers/layer_impl.h"
20 #include "cc/layers/picture_layer.h"
21 #include "cc/test/fake_content_layer_client.h"
22 #include "cc/test/fake_layer_tree_host_client.h"
23 #include "cc/test/fake_picture_layer.h"
24 #include "cc/test/fake_picture_layer_impl.h"
25 #include "cc/test/geometry_test_utils.h"
26 #include "cc/test/layer_tree_test.h"
27 #include "cc/test/test_task_graph_runner.h"
28 #include "cc/test/test_ukm_recorder_factory.h"
29 #include "cc/trees/clip_node.h"
30 #include "cc/trees/effect_node.h"
31 #include "cc/trees/layer_tree_impl.h"
32 #include "cc/trees/scroll_node.h"
33 #include "cc/trees/transform_node.h"
34 #include "components/viz/common/frame_sinks/begin_frame_source.h"
35 #include "testing/gmock/include/gmock/gmock.h"
36 #include "ui/gfx/geometry/point_conversions.h"
37 #include "ui/gfx/geometry/size_conversions.h"
38 #include "ui/gfx/geometry/vector2d_conversions.h"
39
40 using ::testing::Mock;
41
42 namespace cc {
43 namespace {
44
BeginState(const gfx::Point & point)45 std::unique_ptr<ScrollState> BeginState(const gfx::Point& point) {
46 ScrollStateData scroll_state_data;
47 scroll_state_data.is_beginning = true;
48 scroll_state_data.position_x = point.x();
49 scroll_state_data.position_y = point.y();
50 std::unique_ptr<ScrollState> scroll_state(new ScrollState(scroll_state_data));
51 return scroll_state;
52 }
53
UpdateState(const gfx::Point & point,const gfx::Vector2dF & delta)54 std::unique_ptr<ScrollState> UpdateState(const gfx::Point& point,
55 const gfx::Vector2dF& delta) {
56 ScrollStateData scroll_state_data;
57 scroll_state_data.delta_x = delta.x();
58 scroll_state_data.delta_y = delta.y();
59 scroll_state_data.position_x = point.x();
60 scroll_state_data.position_y = point.y();
61 std::unique_ptr<ScrollState> scroll_state(new ScrollState(scroll_state_data));
62 return scroll_state;
63 }
64
65 class LayerTreeHostScrollTest : public LayerTreeTest, public ScrollCallbacks {
66 protected:
LayerTreeHostScrollTest()67 LayerTreeHostScrollTest() { SetUseLayerLists(); }
68
SetupTree()69 void SetupTree() override {
70 LayerTreeTest::SetupTree();
71 Layer* root_layer = layer_tree_host()->root_layer();
72
73 // Create an effective max_scroll_offset of (100, 100).
74 gfx::Size scroll_layer_bounds(root_layer->bounds().width() + 100,
75 root_layer->bounds().height() + 100);
76
77 SetupViewport(root_layer, root_layer->bounds(), scroll_layer_bounds);
78 layer_tree_host()->property_trees()->scroll_tree.SetScrollCallbacks(
79 weak_ptr_factory_.GetWeakPtr());
80 }
81
82 // ScrollCallbacks
DidScroll(ElementId element_id,const gfx::ScrollOffset & scroll_offset,const base::Optional<TargetSnapAreaElementIds> & snap_target_ids)83 void DidScroll(ElementId element_id,
84 const gfx::ScrollOffset& scroll_offset,
85 const base::Optional<TargetSnapAreaElementIds>&
86 snap_target_ids) override {
87 // Simulates cc client (e.g Blink) behavior when handling impl-side scrolls.
88 SetScrollOffsetFromImplSide(layer_tree_host()->LayerByElementId(element_id),
89 scroll_offset);
90
91 if (element_id ==
92 layer_tree_host()->OuterViewportScrollLayerForTesting()->element_id()) {
93 DidScrollOuterViewport(scroll_offset);
94 }
95 if (snap_target_ids.has_value()) {
96 ScrollNode* scroller_node =
97 layer_tree_host()
98 ->property_trees()
99 ->scroll_tree.FindNodeFromElementId(element_id);
100 scroller_node->snap_container_data.value().SetTargetSnapAreaElementIds(
101 snap_target_ids.value());
102 }
103 }
DidChangeScrollbarsHidden(ElementId,bool)104 void DidChangeScrollbarsHidden(ElementId, bool) override {}
105
DidScrollOuterViewport(const gfx::ScrollOffset & scroll_offset)106 virtual void DidScrollOuterViewport(const gfx::ScrollOffset& scroll_offset) {
107 num_outer_viewport_scrolls_++;
108 }
109
110 int num_outer_viewport_scrolls_ = 0;
111
112 private:
113 base::WeakPtrFactory<LayerTreeHostScrollTest> weak_ptr_factory_{this};
114 };
115
116 class LayerTreeHostScrollTestScrollSimple : public LayerTreeHostScrollTest {
117 public:
LayerTreeHostScrollTestScrollSimple()118 LayerTreeHostScrollTestScrollSimple()
119 : initial_scroll_(10, 20), second_scroll_(40, 5), scroll_amount_(2, -1) {}
120
BeginTest()121 void BeginTest() override {
122 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
123 initial_scroll_);
124 PostSetNeedsCommitToMainThread();
125 }
126
UpdateLayerTreeHost()127 void UpdateLayerTreeHost() override {
128 Layer* scroll_layer =
129 layer_tree_host()->OuterViewportScrollLayerForTesting();
130 if (!layer_tree_host()->SourceFrameNumber()) {
131 EXPECT_VECTOR_EQ(initial_scroll_,
132 GetTransformNode(scroll_layer)->scroll_offset);
133 } else {
134 EXPECT_VECTOR_EQ(
135 gfx::ScrollOffsetWithDelta(initial_scroll_, scroll_amount_),
136 GetTransformNode(scroll_layer)->scroll_offset);
137
138 // Pretend like Javascript updated the scroll position itself.
139 SetScrollOffset(scroll_layer, second_scroll_);
140 }
141 }
142
DrawLayersOnThread(LayerTreeHostImpl * impl)143 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
144 LayerImpl* root = impl->active_tree()->root_layer();
145 LayerImpl* scroll_layer =
146 impl->active_tree()->OuterViewportScrollLayerForTesting();
147 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer));
148
149 scroll_layer->SetBounds(
150 gfx::Size(root->bounds().width() + 100, root->bounds().height() + 100));
151 scroll_layer->ScrollBy(scroll_amount_);
152
153 switch (impl->active_tree()->source_frame_number()) {
154 case 0:
155 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
156 EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer));
157 PostSetNeedsCommitToMainThread();
158 break;
159 case 1:
160 EXPECT_VECTOR_EQ(second_scroll_, ScrollOffsetBase(scroll_layer));
161 EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer));
162 EndTest();
163 break;
164 }
165 }
166
AfterTest()167 void AfterTest() override { EXPECT_EQ(1, num_outer_viewport_scrolls_); }
168
169 private:
170 gfx::ScrollOffset initial_scroll_;
171 gfx::ScrollOffset second_scroll_;
172 gfx::Vector2dF scroll_amount_;
173 };
174
175 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSimple);
176
177 class LayerTreeHostScrollTestScrollMultipleRedraw
178 : public LayerTreeHostScrollTest {
179 public:
LayerTreeHostScrollTestScrollMultipleRedraw()180 LayerTreeHostScrollTestScrollMultipleRedraw()
181 : initial_scroll_(40, 10), scroll_amount_(-3, 17) {}
182
BeginTest()183 void BeginTest() override {
184 scroll_layer_ = layer_tree_host()->OuterViewportScrollLayerForTesting();
185 SetScrollOffset(scroll_layer_.get(), initial_scroll_);
186 PostSetNeedsCommitToMainThread();
187 }
188
BeginCommitOnThread(LayerTreeHostImpl * impl)189 void BeginCommitOnThread(LayerTreeHostImpl* impl) override {
190 switch (layer_tree_host()->SourceFrameNumber()) {
191 case 0:
192 EXPECT_VECTOR_EQ(initial_scroll_,
193 CurrentScrollOffset(scroll_layer_.get()));
194 break;
195 case 1:
196 case 2:
197 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(
198 initial_scroll_, scroll_amount_ + scroll_amount_),
199 CurrentScrollOffset(scroll_layer_.get()));
200 break;
201 }
202 }
203
DrawLayersOnThread(LayerTreeHostImpl * impl)204 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
205 LayerImpl* scroll_layer =
206 impl->active_tree()->LayerById(scroll_layer_->id());
207 if (impl->active_tree()->source_frame_number() == 0 &&
208 impl->SourceAnimationFrameNumberForTesting() == 1) {
209 // First draw after first commit.
210 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer));
211 scroll_layer->ScrollBy(scroll_amount_);
212 EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer));
213
214 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
215 PostSetNeedsRedrawToMainThread();
216 } else if (impl->active_tree()->source_frame_number() == 0 &&
217 impl->SourceAnimationFrameNumberForTesting() == 2) {
218 // Second draw after first commit.
219 EXPECT_VECTOR_EQ(ScrollDelta(scroll_layer), scroll_amount_);
220 scroll_layer->ScrollBy(scroll_amount_);
221 EXPECT_VECTOR_EQ(scroll_amount_ + scroll_amount_,
222 ScrollDelta(scroll_layer));
223
224 EXPECT_VECTOR_EQ(initial_scroll_,
225 CurrentScrollOffset(scroll_layer_.get()));
226 PostSetNeedsCommitToMainThread();
227 } else if (impl->active_tree()->source_frame_number() == 1) {
228 // Third or later draw after second commit.
229 EXPECT_GE(impl->SourceAnimationFrameNumberForTesting(), 3u);
230 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(
231 initial_scroll_, scroll_amount_ + scroll_amount_),
232 CurrentScrollOffset(scroll_layer_.get()));
233 EndTest();
234 }
235 }
236
AfterTest()237 void AfterTest() override { EXPECT_EQ(1, num_outer_viewport_scrolls_); }
238
239 private:
240 gfx::ScrollOffset initial_scroll_;
241 gfx::Vector2dF scroll_amount_;
242 scoped_refptr<Layer> scroll_layer_;
243 };
244
245 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollMultipleRedraw);
246
247 class LayerTreeHostScrollTestScrollAbortedCommit
248 : public LayerTreeHostScrollTest {
249 public:
LayerTreeHostScrollTestScrollAbortedCommit()250 LayerTreeHostScrollTestScrollAbortedCommit()
251 : initial_scroll_(50, 60),
252 impl_scroll_(-3, 2),
253 second_main_scroll_(14, -3),
254 impl_scale_(2.f),
255 num_will_begin_main_frames_(0),
256 num_did_begin_main_frames_(0),
257 num_will_commits_(0),
258 num_did_commits_(0),
259 num_impl_commits_(0) {}
260
BeginTest()261 void BeginTest() override {
262 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
263 initial_scroll_);
264 PostSetNeedsCommitToMainThread();
265 }
266
SetupTree()267 void SetupTree() override {
268 LayerTreeHostScrollTest::SetupTree();
269
270 gfx::Size scroll_layer_bounds(200, 200);
271 layer_tree_host()->OuterViewportScrollLayerForTesting()->SetBounds(
272 scroll_layer_bounds);
273 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
274 }
275
WillBeginMainFrame()276 void WillBeginMainFrame() override {
277 num_will_begin_main_frames_++;
278 Layer* root_scroll_layer =
279 layer_tree_host()->OuterViewportScrollLayerForTesting();
280 switch (num_will_begin_main_frames_) {
281 case 1:
282 // This will not be aborted because of the initial prop changes.
283 EXPECT_EQ(0, num_outer_viewport_scrolls_);
284 EXPECT_EQ(0, layer_tree_host()->SourceFrameNumber());
285 EXPECT_VECTOR_EQ(initial_scroll_,
286 CurrentScrollOffset(root_scroll_layer));
287 EXPECT_EQ(1.f, layer_tree_host()->page_scale_factor());
288 break;
289 case 2:
290 // This commit will be aborted, and another commit will be
291 // initiated from the redraw.
292 EXPECT_EQ(1, num_outer_viewport_scrolls_);
293 EXPECT_EQ(1, layer_tree_host()->SourceFrameNumber());
294 EXPECT_VECTOR_EQ(
295 gfx::ScrollOffsetWithDelta(initial_scroll_, impl_scroll_),
296 CurrentScrollOffset(root_scroll_layer));
297 EXPECT_EQ(impl_scale_, layer_tree_host()->page_scale_factor());
298 PostSetNeedsRedrawToMainThread();
299 break;
300 case 3:
301 // This commit will not be aborted because of the scroll change.
302 EXPECT_EQ(2, num_outer_viewport_scrolls_);
303 // The source frame number still increases even with the abort.
304 EXPECT_EQ(2, layer_tree_host()->SourceFrameNumber());
305 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(
306 initial_scroll_, impl_scroll_ + impl_scroll_),
307 CurrentScrollOffset(root_scroll_layer));
308 EXPECT_EQ(impl_scale_ * impl_scale_,
309 layer_tree_host()->page_scale_factor());
310 SetScrollOffset(
311 root_scroll_layer,
312 gfx::ScrollOffsetWithDelta(CurrentScrollOffset(root_scroll_layer),
313 second_main_scroll_));
314 break;
315 case 4:
316 // This commit will also be aborted.
317 EXPECT_EQ(3, num_outer_viewport_scrolls_);
318 EXPECT_EQ(3, layer_tree_host()->SourceFrameNumber());
319 gfx::Vector2dF delta =
320 impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_;
321 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
322 CurrentScrollOffset(root_scroll_layer));
323
324 // End the test by drawing to verify this commit is also aborted.
325 PostSetNeedsRedrawToMainThread();
326 break;
327 }
328 }
329
DidBeginMainFrame()330 void DidBeginMainFrame() override { num_did_begin_main_frames_++; }
331
WillCommit()332 void WillCommit() override { num_will_commits_++; }
333
DidCommit()334 void DidCommit() override { num_did_commits_++; }
335
BeginCommitOnThread(LayerTreeHostImpl * impl)336 void BeginCommitOnThread(LayerTreeHostImpl* impl) override {
337 num_impl_commits_++;
338 }
339
DrawLayersOnThread(LayerTreeHostImpl * impl)340 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
341 LayerImpl* root_scroll_layer =
342 impl->active_tree()->OuterViewportScrollLayerForTesting();
343
344 if (impl->active_tree()->source_frame_number() == 0 &&
345 impl->SourceAnimationFrameNumberForTesting() == 1) {
346 // First draw
347 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer));
348 root_scroll_layer->ScrollBy(impl_scroll_);
349 EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer));
350 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(root_scroll_layer));
351
352 EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
353 EXPECT_EQ(1.f, impl->active_tree()->current_page_scale_factor());
354 impl->active_tree()->SetPageScaleOnActiveTree(impl_scale_);
355 EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
356 EXPECT_EQ(impl_scale_, impl->active_tree()->current_page_scale_factor());
357
358 // To simplify the testing flow, don't redraw here, just commit.
359 impl->SetNeedsCommit();
360 } else if (impl->active_tree()->source_frame_number() == 0 &&
361 impl->SourceAnimationFrameNumberForTesting() == 2) {
362 // Test a second draw after an aborted commit.
363 // The scroll/scale values should be baked into the offset/scale factor
364 // since the main thread consumed but aborted the begin frame.
365 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer));
366 root_scroll_layer->ScrollBy(impl_scroll_);
367 EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer));
368 EXPECT_VECTOR_EQ(
369 gfx::ScrollOffsetWithDelta(initial_scroll_, impl_scroll_),
370 ScrollOffsetBase(root_scroll_layer));
371
372 EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
373 EXPECT_EQ(impl_scale_, impl->active_tree()->current_page_scale_factor());
374 impl->active_tree()->SetPageScaleOnActiveTree(impl_scale_ * impl_scale_);
375 EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
376 EXPECT_EQ(impl_scale_ * impl_scale_,
377 impl->active_tree()->current_page_scale_factor());
378
379 impl->SetNeedsCommit();
380 } else if (impl->active_tree()->source_frame_number() == 1) {
381 // Commit for source frame 1 is aborted.
382 NOTREACHED();
383 } else if (impl->active_tree()->source_frame_number() == 2 &&
384 impl->SourceAnimationFrameNumberForTesting() == 3) {
385 // Third draw after the second full commit.
386 EXPECT_EQ(ScrollDelta(root_scroll_layer), gfx::ScrollOffset());
387 root_scroll_layer->ScrollBy(impl_scroll_);
388 impl->SetNeedsCommit();
389 EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer));
390 gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + second_main_scroll_;
391 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
392 ScrollOffsetBase(root_scroll_layer));
393 } else if (impl->active_tree()->source_frame_number() == 2 &&
394 impl->SourceAnimationFrameNumberForTesting() == 4) {
395 // Final draw after the second aborted commit.
396 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer));
397 gfx::Vector2dF delta =
398 impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_;
399 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
400 ScrollOffsetBase(root_scroll_layer));
401 EndTest();
402 } else {
403 // Commit for source frame 3 is aborted.
404 NOTREACHED();
405 }
406 }
407
AfterTest()408 void AfterTest() override {
409 EXPECT_EQ(3, num_outer_viewport_scrolls_);
410 // Verify that the embedder sees aborted commits as real commits.
411 EXPECT_EQ(4, num_will_begin_main_frames_);
412 EXPECT_EQ(4, num_did_begin_main_frames_);
413 EXPECT_EQ(4, num_will_commits_);
414 EXPECT_EQ(4, num_did_commits_);
415 // ...but the compositor thread only sees two real ones.
416 EXPECT_EQ(2, num_impl_commits_);
417 }
418
419 private:
420 gfx::ScrollOffset initial_scroll_;
421 gfx::Vector2dF impl_scroll_;
422 gfx::Vector2dF second_main_scroll_;
423 float impl_scale_;
424 int num_will_begin_main_frames_;
425 int num_did_begin_main_frames_;
426 int num_will_commits_;
427 int num_did_commits_;
428 int num_impl_commits_;
429 };
430
431 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollAbortedCommit);
432
433 class LayerTreeHostScrollTestFractionalScroll : public LayerTreeHostScrollTest {
434 public:
LayerTreeHostScrollTestFractionalScroll()435 LayerTreeHostScrollTestFractionalScroll() : scroll_amount_(1.75, 0) {}
436
SetupTree()437 void SetupTree() override {
438 LayerTreeHostScrollTest::SetupTree();
439 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
440 }
441
BeginTest()442 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
443
DrawLayersOnThread(LayerTreeHostImpl * impl)444 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
445 LayerImpl* scroll_layer =
446 impl->active_tree()->OuterViewportScrollLayerForTesting();
447
448 // Check that a fractional scroll delta is correctly accumulated over
449 // multiple commits.
450 switch (impl->active_tree()->source_frame_number()) {
451 case 0:
452 EXPECT_VECTOR_EQ(gfx::Vector2d(0, 0), ScrollOffsetBase(scroll_layer));
453 EXPECT_VECTOR_EQ(gfx::Vector2d(0, 0), ScrollDelta(scroll_layer));
454 PostSetNeedsCommitToMainThread();
455 break;
456 case 1:
457 EXPECT_VECTOR_EQ(gfx::ToRoundedVector2d(scroll_amount_),
458 ScrollOffsetBase(scroll_layer));
459 EXPECT_VECTOR_EQ(
460 scroll_amount_ - gfx::ToRoundedVector2d(scroll_amount_),
461 ScrollDelta(scroll_layer));
462 PostSetNeedsCommitToMainThread();
463 break;
464 case 2:
465 EXPECT_VECTOR_EQ(
466 gfx::ToRoundedVector2d(scroll_amount_ + scroll_amount_),
467 ScrollOffsetBase(scroll_layer));
468 EXPECT_VECTOR_EQ(
469 scroll_amount_ + scroll_amount_ -
470 gfx::ToRoundedVector2d(scroll_amount_ + scroll_amount_),
471 ScrollDelta(scroll_layer));
472 EndTest();
473 break;
474 }
475 scroll_layer->ScrollBy(scroll_amount_);
476 }
477
478 private:
479 gfx::Vector2dF scroll_amount_;
480 };
481
482 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestFractionalScroll);
483
484 class LayerTreeHostScrollTestScrollSnapping : public LayerTreeHostScrollTest {
485 public:
LayerTreeHostScrollTestScrollSnapping()486 LayerTreeHostScrollTestScrollSnapping() : scroll_amount_(1.75, 0) {}
487
SetupTree()488 void SetupTree() override {
489 LayerTreeHostScrollTest::SetupTree();
490
491 scoped_refptr<Layer> container = Layer::Create();
492 container->SetBounds(gfx::Size(100, 100));
493 CopyProperties(layer_tree_host()->OuterViewportScrollLayerForTesting(),
494 container.get());
495 CreateTransformNode(container.get()).post_translation =
496 gfx::Vector2dF(0.25, 0);
497 CreateEffectNode(container.get()).render_surface_reason =
498 RenderSurfaceReason::kTest;
499 layer_tree_host()->root_layer()->AddChild(container);
500
501 scroll_layer_ = Layer::Create();
502 scroll_layer_->SetBounds(gfx::Size(200, 200));
503 scroll_layer_->SetIsDrawable(true);
504 scroll_layer_->SetElementId(
505 LayerIdToElementIdForTesting(scroll_layer_->id()));
506 CopyProperties(container.get(), scroll_layer_.get());
507 CreateTransformNode(scroll_layer_.get());
508 CreateScrollNode(scroll_layer_.get(), gfx::Size(100, 100));
509 layer_tree_host()->root_layer()->AddChild(scroll_layer_);
510
511 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.1f, 100.f);
512 }
513
BeginTest()514 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
515
DrawLayersOnThread(LayerTreeHostImpl * impl)516 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
517 LayerImpl* scroll_layer =
518 impl->active_tree()->LayerById(scroll_layer_->id());
519
520 gfx::Transform translate;
521
522 // Check that screen space transform of the scrollable layer is correctly
523 // snapped to integers.
524 switch (impl->active_tree()->source_frame_number()) {
525 case 0:
526 EXPECT_EQ(gfx::Transform(),
527 scroll_layer->draw_properties().screen_space_transform);
528 PostSetNeedsCommitToMainThread();
529 break;
530 case 1:
531 translate.Translate(-2, 0);
532 EXPECT_EQ(translate,
533 scroll_layer->draw_properties().screen_space_transform);
534 PostSetNeedsCommitToMainThread();
535 break;
536 case 2:
537 translate.Translate(-3, 0);
538 EXPECT_EQ(translate,
539 scroll_layer->draw_properties().screen_space_transform);
540 EndTest();
541 break;
542 }
543 scroll_layer->ScrollBy(scroll_amount_);
544 }
545
546 private:
547 scoped_refptr<Layer> scroll_layer_;
548 gfx::Vector2dF scroll_amount_;
549 };
550
551 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollSnapping);
552
553 class LayerTreeHostScrollTestCaseWithChild : public LayerTreeHostScrollTest {
554 public:
LayerTreeHostScrollTestCaseWithChild()555 LayerTreeHostScrollTestCaseWithChild()
556 : initial_offset_(10, 20),
557 javascript_scroll_(40, 5),
558 scroll_amount_(2, -1) {}
559
SetupTree()560 void SetupTree() override {
561 SetInitialDeviceScaleFactor(device_scale_factor_);
562 SetInitialRootBounds(gfx::Size(10, 10));
563 LayerTreeHostScrollTest::SetupTree();
564 Layer* root_layer = layer_tree_host()->root_layer();
565 Layer* root_scroll_layer =
566 layer_tree_host()->OuterViewportScrollLayerForTesting();
567
568 child_layer_ = Layer::Create();
569 child_layer_->SetElementId(
570 LayerIdToElementIdForTesting(child_layer_->id()));
571 child_layer_->SetBounds(gfx::Size(110, 110));
572
573 gfx::Vector2dF child_layer_offset;
574 // Adjust the child layer horizontally so that scrolls will never hit it.
575 if (scroll_child_layer_) {
576 // Scrolls on the child layer will happen at 5, 5. If they are treated
577 // like device pixels, and device scale factor is 2, then they will
578 // be considered at 2.5, 2.5 in logical pixels, and will miss this layer.
579 child_layer_offset = gfx::Vector2dF(5.f, 5.f);
580 } else {
581 child_layer_offset = gfx::Vector2dF(60.f, 5.f);
582 }
583
584 child_layer_->SetIsDrawable(true);
585 child_layer_->SetHitTestable(true);
586 child_layer_->SetElementId(
587 LayerIdToElementIdForTesting(child_layer_->id()));
588 child_layer_->SetBounds(root_scroll_layer->bounds());
589 root_layer->AddChild(child_layer_);
590
591 CopyProperties(root_scroll_layer, child_layer_.get());
592 CreateTransformNode(child_layer_.get()).post_translation =
593 child_layer_offset;
594 CreateScrollNode(child_layer_.get(), root_layer->bounds());
595
596 if (scroll_child_layer_) {
597 expected_scroll_layer_ = child_layer_.get();
598 expected_no_scroll_layer_ = root_scroll_layer;
599 } else {
600 expected_scroll_layer_ = root_scroll_layer;
601 expected_no_scroll_layer_ = child_layer_.get();
602 }
603
604 SetScrollOffset(expected_scroll_layer_, initial_offset_);
605 }
606
BeginTest()607 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
608
WillCommit()609 void WillCommit() override {
610 // Keep the test committing (otherwise the early out for no update
611 // will stall the test).
612 if (layer_tree_host()->SourceFrameNumber() < 2) {
613 layer_tree_host()->SetNeedsCommit();
614 }
615 }
616
DidScroll(ElementId element_id,const gfx::ScrollOffset & offset,const base::Optional<TargetSnapAreaElementIds> & snap_target_ids)617 void DidScroll(ElementId element_id,
618 const gfx::ScrollOffset& offset,
619 const base::Optional<TargetSnapAreaElementIds>&
620 snap_target_ids) override {
621 LayerTreeHostScrollTest::DidScroll(element_id, offset, snap_target_ids);
622 if (element_id == expected_scroll_layer_->element_id()) {
623 final_scroll_offset_ = CurrentScrollOffset(expected_scroll_layer_);
624 EXPECT_EQ(offset, final_scroll_offset_);
625 EXPECT_EQ(element_id, expected_scroll_layer_->element_id());
626 } else {
627 EXPECT_TRUE(offset.IsZero());
628 }
629 }
630
UpdateLayerTreeHost()631 void UpdateLayerTreeHost() override {
632 EXPECT_VECTOR_EQ(gfx::Vector2d(),
633 CurrentScrollOffset(expected_no_scroll_layer_));
634
635 switch (layer_tree_host()->SourceFrameNumber()) {
636 case 0:
637 EXPECT_VECTOR_EQ(initial_offset_,
638 CurrentScrollOffset(expected_scroll_layer_));
639 break;
640 case 1:
641 EXPECT_VECTOR_EQ(
642 gfx::ScrollOffsetWithDelta(initial_offset_, scroll_amount_),
643 CurrentScrollOffset(expected_scroll_layer_));
644
645 // Pretend like Javascript updated the scroll position itself.
646 SetScrollOffset(expected_scroll_layer_, javascript_scroll_);
647 break;
648 case 2:
649 EXPECT_VECTOR_EQ(
650 gfx::ScrollOffsetWithDelta(javascript_scroll_, scroll_amount_),
651 CurrentScrollOffset(expected_scroll_layer_));
652 break;
653 }
654 }
655
DidActivateTreeOnThread(LayerTreeHostImpl * impl)656 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
657 LayerImpl* inner_scroll =
658 impl->active_tree()->InnerViewportScrollLayerForTesting();
659 LayerImpl* root_scroll_layer_impl =
660 impl->active_tree()->OuterViewportScrollLayerForTesting();
661 LayerImpl* child_layer_impl =
662 root_scroll_layer_impl->layer_tree_impl()->LayerById(
663 child_layer_->id());
664
665 LayerImpl* expected_scroll_layer_impl = nullptr;
666 LayerImpl* expected_no_scroll_layer_impl = nullptr;
667 if (scroll_child_layer_) {
668 expected_scroll_layer_impl = child_layer_impl;
669 expected_no_scroll_layer_impl = root_scroll_layer_impl;
670 } else {
671 expected_scroll_layer_impl = root_scroll_layer_impl;
672 expected_no_scroll_layer_impl = child_layer_impl;
673 }
674
675 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(inner_scroll));
676 EXPECT_VECTOR_EQ(gfx::Vector2d(),
677 ScrollDelta(expected_no_scroll_layer_impl));
678
679 // Ensure device scale factor matches the active tree.
680 EXPECT_EQ(device_scale_factor_, impl->active_tree()->device_scale_factor());
681 switch (impl->active_tree()->source_frame_number()) {
682 case 0: {
683 // GESTURE scroll on impl thread. Also tests that the last scrolled
684 // layer id is stored even after the scrolling ends.
685 gfx::Point scroll_point = gfx::ToCeiledPoint(
686 gfx::PointF(-0.5f, -0.5f) +
687 GetTransformNode(expected_scroll_layer_impl)->post_translation);
688 InputHandler::ScrollStatus status = impl->ScrollBegin(
689 BeginState(scroll_point).get(), ScrollInputType::kTouchscreen);
690 EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
691 impl->ScrollUpdate(UpdateState(gfx::Point(), scroll_amount_).get());
692 auto* scrolling_node = impl->CurrentlyScrollingNode();
693 CHECK(scrolling_node);
694 impl->ScrollEnd();
695 CHECK(!impl->CurrentlyScrollingNode());
696 EXPECT_EQ(scrolling_node->id,
697 impl->active_tree()->LastScrolledScrollNodeIndex());
698
699 // Check the scroll is applied as a delta.
700 EXPECT_VECTOR_EQ(initial_offset_,
701 ScrollOffsetBase(expected_scroll_layer_impl));
702 EXPECT_VECTOR_EQ(scroll_amount_,
703 ScrollDelta(expected_scroll_layer_impl));
704 break;
705 }
706 case 1: {
707 // WHEEL scroll on impl thread.
708 gfx::Point scroll_point = gfx::ToCeiledPoint(
709 gfx::PointF(0.5f, 0.5f) +
710 GetTransformNode(expected_scroll_layer_impl)->post_translation);
711 InputHandler::ScrollStatus status = impl->ScrollBegin(
712 BeginState(scroll_point).get(), ScrollInputType::kWheel);
713 EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
714 impl->ScrollUpdate(UpdateState(gfx::Point(), scroll_amount_).get());
715 impl->ScrollEnd();
716
717 // Check the scroll is applied as a delta.
718 EXPECT_VECTOR_EQ(javascript_scroll_,
719 ScrollOffsetBase(expected_scroll_layer_impl));
720 EXPECT_VECTOR_EQ(scroll_amount_,
721 ScrollDelta(expected_scroll_layer_impl));
722 break;
723 }
724 case 2:
725
726 EXPECT_VECTOR_EQ(
727 gfx::ScrollOffsetWithDelta(javascript_scroll_, scroll_amount_),
728 ScrollOffsetBase(expected_scroll_layer_impl));
729 EXPECT_VECTOR_EQ(gfx::Vector2d(),
730 ScrollDelta(expected_scroll_layer_impl));
731
732 EndTest();
733 break;
734 }
735 }
736
AfterTest()737 void AfterTest() override {
738 EXPECT_EQ(scroll_child_layer_ ? 0 : 2, num_outer_viewport_scrolls_);
739 EXPECT_VECTOR_EQ(
740 gfx::ScrollOffsetWithDelta(javascript_scroll_, scroll_amount_),
741 final_scroll_offset_);
742 }
743
744 protected:
745 float device_scale_factor_;
746 bool scroll_child_layer_;
747
748 gfx::ScrollOffset initial_offset_;
749 gfx::ScrollOffset javascript_scroll_;
750 gfx::Vector2d scroll_amount_;
751 gfx::ScrollOffset final_scroll_offset_;
752
753 scoped_refptr<Layer> child_layer_;
754 Layer* expected_scroll_layer_;
755 Layer* expected_no_scroll_layer_;
756 };
757
TEST_F(LayerTreeHostScrollTestCaseWithChild,DeviceScaleFactor1_ScrollChild)758 TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor1_ScrollChild) {
759 device_scale_factor_ = 1.f;
760 scroll_child_layer_ = true;
761 RunTest(CompositorMode::THREADED);
762 }
763
TEST_F(LayerTreeHostScrollTestCaseWithChild,DeviceScaleFactor15_ScrollChild)764 TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor15_ScrollChild) {
765 device_scale_factor_ = 1.5f;
766 scroll_child_layer_ = true;
767 RunTest(CompositorMode::THREADED);
768 }
769
TEST_F(LayerTreeHostScrollTestCaseWithChild,DeviceScaleFactor2_ScrollChild)770 TEST_F(LayerTreeHostScrollTestCaseWithChild, DeviceScaleFactor2_ScrollChild) {
771 device_scale_factor_ = 2.f;
772 scroll_child_layer_ = true;
773 RunTest(CompositorMode::THREADED);
774 }
775
TEST_F(LayerTreeHostScrollTestCaseWithChild,DeviceScaleFactor1_ScrollRootScrollLayer)776 TEST_F(LayerTreeHostScrollTestCaseWithChild,
777 DeviceScaleFactor1_ScrollRootScrollLayer) {
778 device_scale_factor_ = 1.f;
779 scroll_child_layer_ = false;
780 RunTest(CompositorMode::THREADED);
781 }
782
TEST_F(LayerTreeHostScrollTestCaseWithChild,DeviceScaleFactor15_ScrollRootScrollLayer)783 TEST_F(LayerTreeHostScrollTestCaseWithChild,
784 DeviceScaleFactor15_ScrollRootScrollLayer) {
785 device_scale_factor_ = 1.5f;
786 scroll_child_layer_ = false;
787 RunTest(CompositorMode::THREADED);
788 }
789
TEST_F(LayerTreeHostScrollTestCaseWithChild,DeviceScaleFactor2_ScrollRootScrollLayer)790 TEST_F(LayerTreeHostScrollTestCaseWithChild,
791 DeviceScaleFactor2_ScrollRootScrollLayer) {
792 device_scale_factor_ = 2.f;
793 scroll_child_layer_ = false;
794 RunTest(CompositorMode::THREADED);
795 }
796
797 class LayerTreeHostScrollTestSimple : public LayerTreeHostScrollTest {
798 public:
LayerTreeHostScrollTestSimple()799 LayerTreeHostScrollTestSimple()
800 : initial_scroll_(10, 20),
801 main_thread_scroll_(40, 5),
802 impl_thread_scroll1_(2, -1),
803 impl_thread_scroll2_(-3, 10) {}
804
SetupTree()805 void SetupTree() override {
806 LayerTreeHostScrollTest::SetupTree();
807 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
808 }
809
BeginTest()810 void BeginTest() override {
811 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
812 initial_scroll_);
813 PostSetNeedsCommitToMainThread();
814 }
815
UpdateLayerTreeHost()816 void UpdateLayerTreeHost() override {
817 Layer* scroll_layer =
818 layer_tree_host()->OuterViewportScrollLayerForTesting();
819 if (!layer_tree_host()->SourceFrameNumber()) {
820 EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer));
821 } else {
822 EXPECT_VECTOR_EQ(
823 CurrentScrollOffset(scroll_layer),
824 gfx::ScrollOffsetWithDelta(initial_scroll_, impl_thread_scroll1_));
825
826 // Pretend like Javascript updated the scroll position itself with a
827 // change of main_thread_scroll.
828 SetScrollOffset(
829 scroll_layer,
830 gfx::ScrollOffsetWithDelta(
831 initial_scroll_, main_thread_scroll_ + impl_thread_scroll1_));
832 }
833 }
834
CommitCompleteOnThread(LayerTreeHostImpl * impl)835 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
836 // We force a second draw here of the first commit before activating
837 // the second commit.
838 if (impl->active_tree()->source_frame_number() == 0)
839 impl->SetNeedsRedraw();
840 }
841
DrawLayersOnThread(LayerTreeHostImpl * impl)842 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
843 if (impl->pending_tree())
844 impl->SetNeedsRedraw();
845
846 LayerImpl* root = impl->active_tree()->root_layer();
847 LayerImpl* scroll_layer =
848 impl->active_tree()->OuterViewportScrollLayerForTesting();
849 LayerImpl* pending_root =
850 impl->active_tree()->FindPendingTreeLayerById(root->id());
851
852 switch (impl->active_tree()->source_frame_number()) {
853 case 0:
854 if (!impl->pending_tree()) {
855 impl->BlockNotifyReadyToActivateForTesting(true);
856 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer));
857 scroll_layer->ScrollBy(impl_thread_scroll1_);
858
859 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
860 EXPECT_VECTOR_EQ(impl_thread_scroll1_, ScrollDelta(scroll_layer));
861 PostSetNeedsCommitToMainThread();
862
863 // CommitCompleteOnThread will trigger this function again
864 // and cause us to take the else clause.
865 } else {
866 impl->BlockNotifyReadyToActivateForTesting(false);
867 ASSERT_TRUE(pending_root);
868 EXPECT_EQ(impl->pending_tree()->source_frame_number(), 1);
869
870 scroll_layer->ScrollBy(impl_thread_scroll2_);
871 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
872 EXPECT_VECTOR_EQ(impl_thread_scroll1_ + impl_thread_scroll2_,
873 ScrollDelta(scroll_layer));
874
875 LayerImpl* pending_scroll_layer =
876 impl->pending_tree()->OuterViewportScrollLayerForTesting();
877 EXPECT_VECTOR_EQ(
878 gfx::ScrollOffsetWithDelta(
879 initial_scroll_, main_thread_scroll_ + impl_thread_scroll1_),
880 ScrollOffsetBase(pending_scroll_layer));
881 EXPECT_VECTOR_EQ(impl_thread_scroll2_,
882 ScrollDelta(pending_scroll_layer));
883 }
884 break;
885 case 1:
886 EXPECT_FALSE(impl->pending_tree());
887 EXPECT_VECTOR_EQ(
888 gfx::ScrollOffsetWithDelta(
889 initial_scroll_, main_thread_scroll_ + impl_thread_scroll1_),
890 ScrollOffsetBase(scroll_layer));
891 EXPECT_VECTOR_EQ(impl_thread_scroll2_, ScrollDelta(scroll_layer));
892 EndTest();
893 break;
894 }
895 }
896
AfterTest()897 void AfterTest() override { EXPECT_EQ(1, num_outer_viewport_scrolls_); }
898
899 private:
900 gfx::ScrollOffset initial_scroll_;
901 gfx::Vector2dF main_thread_scroll_;
902 gfx::Vector2dF impl_thread_scroll1_;
903 gfx::Vector2dF impl_thread_scroll2_;
904 };
905
906 // This tests scrolling on the impl side which is only possible with a thread.
907 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestSimple);
908
909 // This test makes sure that layers pick up scrolls that occur between
910 // beginning a commit and finishing a commit (aka scroll deltas not
911 // included in sent scroll delta) still apply to layers that don't
912 // push properties.
913 class LayerTreeHostScrollTestImplOnlyScroll : public LayerTreeHostScrollTest {
914 public:
LayerTreeHostScrollTestImplOnlyScroll()915 LayerTreeHostScrollTestImplOnlyScroll()
916 : initial_scroll_(20, 10), impl_thread_scroll_(-2, 3), impl_scale_(2.f) {}
917
SetupTree()918 void SetupTree() override {
919 LayerTreeHostScrollTest::SetupTree();
920 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
921 }
922
BeginTest()923 void BeginTest() override {
924 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
925 initial_scroll_);
926 PostSetNeedsCommitToMainThread();
927 }
928
WillCommit()929 void WillCommit() override {
930 Layer* scroll_layer =
931 layer_tree_host()->OuterViewportScrollLayerForTesting();
932 switch (layer_tree_host()->SourceFrameNumber()) {
933 case 0:
934 EXPECT_TRUE(base::Contains(
935 scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(),
936 scroll_layer));
937 break;
938 case 1:
939 // Even if this layer doesn't need push properties, it should
940 // still pick up scrolls that happen on the active layer during
941 // commit.
942 EXPECT_FALSE(base::Contains(
943 scroll_layer->layer_tree_host()->LayersThatShouldPushProperties(),
944 scroll_layer));
945 break;
946 }
947 }
948
BeginCommitOnThread(LayerTreeHostImpl * impl)949 void BeginCommitOnThread(LayerTreeHostImpl* impl) override {
950 // Scroll after the 2nd commit has started.
951 if (impl->active_tree()->source_frame_number() == 0) {
952 LayerImpl* active_root = impl->active_tree()->root_layer();
953 LayerImpl* active_scroll_layer =
954 impl->active_tree()->OuterViewportScrollLayerForTesting();
955 ASSERT_TRUE(active_root);
956 ASSERT_TRUE(active_scroll_layer);
957 active_scroll_layer->ScrollBy(impl_thread_scroll_);
958 impl->active_tree()->SetPageScaleOnActiveTree(impl_scale_);
959 }
960 }
961
CommitCompleteOnThread(LayerTreeHostImpl * impl)962 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
963 // We force a second draw here of the first commit before activating
964 // the second commit.
965 LayerImpl* active_root = impl->active_tree()->root_layer();
966 LayerImpl* active_scroll_layer =
967 active_root ? impl->active_tree()->OuterViewportScrollLayerForTesting()
968 : nullptr;
969 LayerImpl* pending_root = impl->pending_tree()->root_layer();
970 LayerImpl* pending_scroll_layer =
971 impl->pending_tree()->OuterViewportScrollLayerForTesting();
972
973 ASSERT_TRUE(pending_root);
974 ASSERT_TRUE(pending_scroll_layer);
975 switch (impl->pending_tree()->source_frame_number()) {
976 case 0:
977 EXPECT_VECTOR_EQ(initial_scroll_,
978 ScrollOffsetBase(pending_scroll_layer));
979 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(pending_scroll_layer));
980 EXPECT_FALSE(active_root);
981 break;
982 case 1:
983 // Even though the scroll happened during the commit, both layers
984 // should have the appropriate scroll delta.
985 EXPECT_VECTOR_EQ(initial_scroll_,
986 ScrollOffsetBase(pending_scroll_layer));
987 EXPECT_VECTOR_EQ(impl_thread_scroll_,
988 ScrollDelta(pending_scroll_layer));
989 ASSERT_TRUE(active_root);
990 EXPECT_VECTOR_EQ(initial_scroll_,
991 ScrollOffsetBase(active_scroll_layer));
992 EXPECT_VECTOR_EQ(impl_thread_scroll_, ScrollDelta(active_scroll_layer));
993 break;
994 case 2:
995 // On the next commit, this delta should have been sent and applied.
996 EXPECT_VECTOR_EQ(
997 gfx::ScrollOffsetWithDelta(initial_scroll_, impl_thread_scroll_),
998 ScrollOffsetBase(pending_scroll_layer));
999 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(pending_scroll_layer));
1000 break;
1001 }
1002
1003 // Ensure that the scroll-offsets on the TransformTree are consistent with
1004 // the synced scroll offsets, for the pending tree.
1005 if (!impl->pending_tree())
1006 return;
1007
1008 LayerImpl* scroll_layer =
1009 impl->pending_tree()->OuterViewportScrollLayerForTesting();
1010 gfx::ScrollOffset scroll_offset = CurrentScrollOffset(scroll_layer);
1011 int transform_index = scroll_layer->transform_tree_index();
1012 gfx::ScrollOffset transform_tree_scroll_offset =
1013 impl->pending_tree()
1014 ->property_trees()
1015 ->transform_tree.Node(transform_index)
1016 ->scroll_offset;
1017 EXPECT_EQ(scroll_offset, transform_tree_scroll_offset);
1018 }
1019
DrawLayersOnThread(LayerTreeHostImpl * impl)1020 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1021 if (impl->pending_tree())
1022 impl->SetNeedsRedraw();
1023
1024 LayerImpl* scroll_layer =
1025 impl->active_tree()->OuterViewportScrollLayerForTesting();
1026
1027 switch (impl->active_tree()->source_frame_number()) {
1028 case 0:
1029 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
1030 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer));
1031 EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
1032 EXPECT_EQ(1.f, impl->active_tree()->current_page_scale_factor());
1033 PostSetNeedsCommitToMainThread();
1034 break;
1035 case 1:
1036 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
1037 EXPECT_VECTOR_EQ(impl_thread_scroll_, ScrollDelta(scroll_layer));
1038 EXPECT_EQ(impl_scale_, impl->active_tree()->page_scale_delta());
1039 EXPECT_EQ(impl_scale_,
1040 impl->active_tree()->current_page_scale_factor());
1041 PostSetNeedsCommitToMainThread();
1042 break;
1043 case 2:
1044 EXPECT_EQ(1.f, impl->active_tree()->page_scale_delta());
1045 EXPECT_EQ(impl_scale_,
1046 impl->active_tree()->current_page_scale_factor());
1047 EndTest();
1048 break;
1049 }
1050 }
1051
1052 private:
1053 gfx::ScrollOffset initial_scroll_;
1054 gfx::Vector2dF impl_thread_scroll_;
1055 float impl_scale_;
1056 };
1057
1058 // This tests scrolling on the impl side which is only possible with a thread.
1059 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyScroll);
1060
DoGestureScroll(LayerTreeHostImpl * host_impl,const scoped_refptr<Layer> & scroller,gfx::Vector2dF offset)1061 void DoGestureScroll(LayerTreeHostImpl* host_impl,
1062 const scoped_refptr<Layer>& scroller,
1063 gfx::Vector2dF offset) {
1064 ScrollStateData begin_scroll_state_data;
1065 begin_scroll_state_data.set_current_native_scrolling_element(
1066 scroller->element_id());
1067 begin_scroll_state_data.delta_x_hint = offset.x();
1068 begin_scroll_state_data.delta_y_hint = offset.y();
1069 std::unique_ptr<ScrollState> begin_scroll_state(
1070 new ScrollState(begin_scroll_state_data));
1071 auto scroll_status = host_impl->ScrollBegin(begin_scroll_state.get(),
1072 ScrollInputType::kTouchscreen);
1073 EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, scroll_status.thread);
1074 auto* scrolling_node = host_impl->CurrentlyScrollingNode();
1075 EXPECT_TRUE(scrolling_node);
1076 EXPECT_EQ(scrolling_node->element_id, scroller->element_id());
1077
1078 ScrollStateData update_scroll_state_data;
1079 update_scroll_state_data.delta_x = offset.x();
1080 update_scroll_state_data.delta_y = offset.y();
1081 std::unique_ptr<ScrollState> update_scroll_state(
1082 new ScrollState(update_scroll_state_data));
1083 host_impl->ScrollUpdate(update_scroll_state.get());
1084
1085 host_impl->ScrollEnd(true /* should_snap */);
1086 }
1087
1088 // This test simulates scrolling on the impl thread such that snapping occurs
1089 // and ensures that the target snap area element ids are sent back to the main
1090 // thread.
1091 class LayerTreeHostScrollTestImplOnlyScrollSnap
1092 : public LayerTreeHostScrollTest {
1093 public:
LayerTreeHostScrollTestImplOnlyScrollSnap()1094 LayerTreeHostScrollTestImplOnlyScrollSnap()
1095 : initial_scroll_(100, 100),
1096 impl_thread_scroll_(350, 350),
1097 snap_area_id_(ElementId(10)) {}
1098
SetupTree()1099 void SetupTree() override {
1100 LayerTreeHostScrollTest::SetupTree();
1101
1102 Layer* root = layer_tree_host()->root_layer();
1103 container_ = Layer::Create();
1104 scroller_ = Layer::Create();
1105 scroller_->SetElementId(LayerIdToElementIdForTesting(scroller_->id()));
1106
1107 container_->SetBounds(gfx::Size(100, 100));
1108 CopyProperties(root, container_.get());
1109 root->AddChild(container_);
1110
1111 scroller_->SetBounds(gfx::Size(1000, 1000));
1112 CopyProperties(container_.get(), scroller_.get());
1113 CreateTransformNode(scroller_.get());
1114
1115 // Set up a snap area.
1116 snap_area_ = Layer::Create();
1117 snap_area_->SetBounds(gfx::Size(50, 50));
1118 snap_area_->SetPosition(gfx::PointF(500, 500));
1119 CopyProperties(scroller_.get(), snap_area_.get());
1120 scroller_->AddChild(snap_area_);
1121 SnapAreaData snap_area_data(ScrollSnapAlign(SnapAlignment::kStart),
1122 gfx::RectF(500, 500, 100, 100), false,
1123 snap_area_id_);
1124
1125 // Set up snap container data.
1126 SnapContainerData snap_container_data(
1127 ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
1128 gfx::RectF(0, 0, 100, 100), gfx::ScrollOffset(900, 900));
1129 snap_container_data.AddSnapAreaData(snap_area_data);
1130 CreateScrollNode(scroller_.get(), container_->bounds())
1131 .snap_container_data = snap_container_data;
1132
1133 root->AddChild(scroller_);
1134 }
1135
BeginTest()1136 void BeginTest() override {
1137 SetScrollOffset(scroller_.get(), initial_scroll_);
1138 PostSetNeedsCommitToMainThread();
1139 }
1140
1141 // The animations states are updated before this call.
WillSendBeginMainFrameOnThread(LayerTreeHostImpl * host_impl)1142 void WillSendBeginMainFrameOnThread(LayerTreeHostImpl* host_impl) override {
1143 if (host_impl->active_tree()->source_frame_number() < 0)
1144 return;
1145
1146 // Perform a scroll such that a snap target is found. This will get pushed
1147 // to the main thread on the next BeginMainFrame.
1148 if (host_impl->active_tree()->source_frame_number() == 0) {
1149 LayerImpl* scroller_impl =
1150 host_impl->active_tree()->LayerById(scroller_->id());
1151
1152 DoGestureScroll(host_impl, scroller_, impl_thread_scroll_);
1153
1154 EXPECT_TRUE(host_impl->IsAnimatingForSnap());
1155 EXPECT_VECTOR_EQ(impl_thread_scroll_, ScrollDelta(scroller_impl));
1156 } else {
1157 snap_animation_finished_ = !host_impl->IsAnimatingForSnap();
1158 }
1159 }
1160
UpdateLayerTreeHost()1161 void UpdateLayerTreeHost() override {
1162 ScrollNode* scroller_node =
1163 layer_tree_host()->property_trees()->scroll_tree.Node(
1164 scroller_->scroll_tree_index());
1165 auto snap_target_ids = scroller_node->snap_container_data.value()
1166 .GetTargetSnapAreaElementIds();
1167 if (layer_tree_host()->SourceFrameNumber() == 0) {
1168 // On the first BeginMainFrame scrolling has not happened yet.
1169 // Check that the scroll offset and scroll snap targets are at the initial
1170 // values on the main thread.
1171 EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroller_.get()));
1172 }
1173 if (snap_animation_finished_) {
1174 // After a snap target is set on the impl thread, the snap targets should
1175 // be pushed to the main thread.
1176 EXPECT_EQ(snap_target_ids,
1177 TargetSnapAreaElementIds(snap_area_id_, snap_area_id_));
1178 EndTest();
1179 } else {
1180 EXPECT_EQ(snap_target_ids, TargetSnapAreaElementIds());
1181 }
1182 }
1183
DidActivateTreeOnThread(LayerTreeHostImpl * host_impl)1184 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1185 PostSetNeedsCommitToMainThread();
1186 }
1187
1188 private:
1189 scoped_refptr<Layer> container_;
1190 scoped_refptr<Layer> scroller_;
1191 scoped_refptr<Layer> snap_area_;
1192
1193 gfx::ScrollOffset initial_scroll_;
1194 gfx::Vector2dF impl_thread_scroll_;
1195
1196 ElementId snap_area_id_;
1197
1198 bool snap_animation_finished_ = false;
1199 };
1200
1201 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyScrollSnap);
1202
1203 // This test simulates scrolling on the impl thread such that 2 impl-only
1204 // scrolls occur between main frames. It ensures that the snap target ids will
1205 // be synced from impl to main for both snapped scrolling nodes.
1206 class LayerTreeHostScrollTestImplOnlyMultipleScrollSnap
1207 : public LayerTreeHostScrollTest {
1208 public:
LayerTreeHostScrollTestImplOnlyMultipleScrollSnap()1209 LayerTreeHostScrollTestImplOnlyMultipleScrollSnap()
1210 : initial_scroll_(100, 100),
1211 // Scroll to the boundary so that an animation is not created when
1212 // snapping to allow 2 scrolls between main frames.
1213 impl_thread_scroll_a_(400, 400),
1214 impl_thread_scroll_b_(400, 400),
1215 snap_area_a_id_(ElementId(10)),
1216 snap_area_b_id_(ElementId(20)) {}
1217
SetupTree()1218 void SetupTree() override {
1219 LayerTreeHostScrollTest::SetupTree();
1220
1221 Layer* root = layer_tree_host()->root_layer();
1222 container_ = Layer::Create();
1223 scroller_a_ = Layer::Create();
1224 scroller_b_ = Layer::Create();
1225 scroller_a_->SetElementId(LayerIdToElementIdForTesting(scroller_a_->id()));
1226 scroller_b_->SetElementId(LayerIdToElementIdForTesting(scroller_b_->id()));
1227
1228 container_->SetBounds(gfx::Size(100, 100));
1229 CopyProperties(root, container_.get());
1230 root->AddChild(container_);
1231
1232 scroller_a_->SetBounds(gfx::Size(1000, 1000));
1233 CopyProperties(container_.get(), scroller_a_.get());
1234 CreateTransformNode(scroller_a_.get());
1235 scroller_b_->SetBounds(gfx::Size(1000, 1000));
1236 CopyProperties(container_.get(), scroller_b_.get());
1237 CreateTransformNode(scroller_b_.get());
1238
1239 // Set up snap areas.
1240 snap_area_a_ = Layer::Create();
1241 snap_area_a_->SetBounds(gfx::Size(50, 50));
1242 snap_area_a_->SetPosition(gfx::PointF(500, 500));
1243 CopyProperties(scroller_a_.get(), snap_area_a_.get());
1244 scroller_a_->AddChild(snap_area_a_);
1245 SnapAreaData snap_area_data_a(ScrollSnapAlign(SnapAlignment::kStart),
1246 gfx::RectF(500, 500, 100, 100), false,
1247 snap_area_a_id_);
1248
1249 snap_area_b_ = Layer::Create();
1250 snap_area_b_->SetBounds(gfx::Size(50, 50));
1251 snap_area_b_->SetPosition(gfx::PointF(500, 500));
1252 CopyProperties(scroller_b_.get(), snap_area_b_.get());
1253 scroller_b_->AddChild(snap_area_b_);
1254 SnapAreaData snap_area_data_b(ScrollSnapAlign(SnapAlignment::kStart),
1255 gfx::RectF(500, 500, 100, 100), false,
1256 snap_area_b_id_);
1257
1258 // Set up snap container data.
1259 SnapContainerData snap_container_data_a(
1260 ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
1261 gfx::RectF(0, 0, 100, 100), gfx::ScrollOffset(900, 900));
1262 snap_container_data_a.AddSnapAreaData(snap_area_data_a);
1263 CreateScrollNode(scroller_a_.get(), container_->bounds())
1264 .snap_container_data = snap_container_data_a;
1265
1266 // Set up snap container data.
1267 SnapContainerData snap_container_data_b(
1268 ScrollSnapType(false, SnapAxis::kBoth, SnapStrictness::kMandatory),
1269 gfx::RectF(0, 0, 100, 100), gfx::ScrollOffset(900, 900));
1270 snap_container_data_b.AddSnapAreaData(snap_area_data_b);
1271 CreateScrollNode(scroller_b_.get(), container_->bounds())
1272 .snap_container_data = snap_container_data_b;
1273
1274 root->AddChild(scroller_a_);
1275 root->AddChild(scroller_b_);
1276 }
1277
BeginTest()1278 void BeginTest() override {
1279 SetScrollOffset(scroller_a_.get(), initial_scroll_);
1280 SetScrollOffset(scroller_b_.get(), initial_scroll_);
1281 PostSetNeedsCommitToMainThread();
1282 }
1283
UpdateLayerTreeHost()1284 void UpdateLayerTreeHost() override {
1285 ScrollNode* scroller_node_a =
1286 layer_tree_host()->property_trees()->scroll_tree.Node(
1287 scroller_a_->scroll_tree_index());
1288 ScrollNode* scroller_node_b =
1289 layer_tree_host()->property_trees()->scroll_tree.Node(
1290 scroller_b_->scroll_tree_index());
1291 auto snap_target_ids_a = scroller_node_a->snap_container_data.value()
1292 .GetTargetSnapAreaElementIds();
1293 auto snap_target_ids_b = scroller_node_b->snap_container_data.value()
1294 .GetTargetSnapAreaElementIds();
1295 if (layer_tree_host()->SourceFrameNumber() == 0) {
1296 // On the first BeginMainFrame scrolling has not happened yet.
1297 // Check that the scroll offset and scroll snap targets are at the initial
1298 // values on the main thread.
1299 EXPECT_EQ(snap_target_ids_a, TargetSnapAreaElementIds());
1300 EXPECT_EQ(snap_target_ids_b, TargetSnapAreaElementIds());
1301 EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroller_a_.get()));
1302 EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroller_b_.get()));
1303 } else {
1304 // When scrolling happens on the impl thread, the snap targets of the
1305 // scrolled layers should be pushed to the main thread.
1306 EXPECT_EQ(snap_target_ids_a,
1307 TargetSnapAreaElementIds(snap_area_a_id_, snap_area_a_id_));
1308 EXPECT_EQ(snap_target_ids_b,
1309 TargetSnapAreaElementIds(snap_area_b_id_, snap_area_b_id_));
1310 EndTest();
1311 }
1312 }
1313
DidActivateTreeOnThread(LayerTreeHostImpl * host_impl)1314 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
1315 // Perform scrolls such that a snap target is found. These will get pushed
1316 // to the main thread on the next BeginMainFrame.
1317 if (host_impl->active_tree()->source_frame_number() == 0) {
1318 LayerImpl* scroller_impl_a =
1319 host_impl->active_tree()->LayerById(scroller_a_->id());
1320 LayerImpl* scroller_impl_b =
1321 host_impl->active_tree()->LayerById(scroller_b_->id());
1322
1323 DoGestureScroll(host_impl, scroller_a_, impl_thread_scroll_a_);
1324 DoGestureScroll(host_impl, scroller_b_, impl_thread_scroll_b_);
1325
1326 EXPECT_VECTOR_EQ(impl_thread_scroll_a_, ScrollDelta(scroller_impl_a));
1327 EXPECT_VECTOR_EQ(impl_thread_scroll_b_, ScrollDelta(scroller_impl_b));
1328 }
1329 PostSetNeedsCommitToMainThread();
1330 }
1331
1332 private:
1333 scoped_refptr<Layer> container_;
1334 scoped_refptr<Layer> scroller_a_;
1335 scoped_refptr<Layer> scroller_b_;
1336 scoped_refptr<Layer> snap_area_a_;
1337 scoped_refptr<Layer> snap_area_b_;
1338
1339 gfx::ScrollOffset initial_scroll_;
1340 gfx::Vector2dF impl_thread_scroll_a_;
1341 gfx::Vector2dF impl_thread_scroll_b_;
1342
1343 ElementId snap_area_a_id_;
1344 ElementId snap_area_b_id_;
1345 };
1346
1347 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplOnlyMultipleScrollSnap);
1348
1349 class LayerTreeHostScrollTestScrollZeroMaxScrollOffset
1350 : public LayerTreeHostScrollTest {
1351 public:
1352 LayerTreeHostScrollTestScrollZeroMaxScrollOffset() = default;
1353
SetupTree()1354 void SetupTree() override {
1355 LayerTreeHostScrollTest::SetupTree();
1356
1357 // Add a sub-scroller to test TryScroll against. The outer viewport scroll
1358 // will be latched to for scrolling even if it doesn't have any scroll
1359 // extent in the given direction to support overscroll actions.
1360 scroller_ = Layer::Create();
1361 scroller_->SetIsDrawable(true);
1362 scroller_->SetHitTestable(true);
1363 scroller_->SetElementId(LayerIdToElementIdForTesting(scroller_->id()));
1364 CopyProperties(layer_tree_host()->OuterViewportScrollLayerForTesting(),
1365 scroller_.get());
1366 CreateTransformNode(scroller_.get());
1367 CreateScrollNode(scroller_.get(),
1368 layer_tree_host()->root_layer()->bounds());
1369 layer_tree_host()->root_layer()->AddChild(scroller_.get());
1370 }
1371
BeginTest()1372 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1373
UpdateLayerTreeHost()1374 void UpdateLayerTreeHost() override {
1375 ScrollTree& scroll_tree = layer_tree_host()->property_trees()->scroll_tree;
1376 ScrollNode* scroll_node = scroll_tree.Node(scroller_->scroll_tree_index());
1377 switch (layer_tree_host()->SourceFrameNumber()) {
1378 case 0:
1379 // Set max_scroll_offset = (100, 100).
1380 scroll_node->bounds = scroll_node->container_bounds;
1381 scroll_node->bounds.Enlarge(100, 100);
1382 break;
1383 case 1:
1384 // Set max_scroll_offset = (0, 0).
1385 scroll_node->bounds = scroll_node->container_bounds;
1386 break;
1387 case 2:
1388 // Set max_scroll_offset = (-1, -1).
1389 scroll_node->bounds = gfx::Size();
1390 break;
1391 }
1392 }
1393
DrawLayersOnThread(LayerTreeHostImpl * impl)1394 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1395 ScrollTree& scroll_tree =
1396 impl->active_tree()->property_trees()->scroll_tree;
1397 ScrollNode* scroll_node = scroll_tree.Node(scroller_->scroll_tree_index());
1398 InputHandler::ScrollStatus status =
1399 impl->TryScroll(scroll_tree, scroll_node);
1400 switch (impl->active_tree()->source_frame_number()) {
1401 case 0:
1402 EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread)
1403 << "In Frame 0";
1404 EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
1405 status.main_thread_scrolling_reasons)
1406 << "In Frame 0";
1407 PostSetNeedsCommitToMainThread();
1408 break;
1409 case 1:
1410 EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread) << "In Frame 1";
1411 EXPECT_EQ(MainThreadScrollingReason::kNotScrollable,
1412 status.main_thread_scrolling_reasons)
1413 << "In Frame 1";
1414 PostSetNeedsCommitToMainThread();
1415 break;
1416 case 2:
1417 EXPECT_EQ(InputHandler::SCROLL_IGNORED, status.thread) << "In Frame 2";
1418 EXPECT_EQ(MainThreadScrollingReason::kNotScrollable,
1419 status.main_thread_scrolling_reasons)
1420 << "In Frame 2";
1421 EndTest();
1422 break;
1423 }
1424 }
1425
1426 private:
1427 scoped_refptr<Layer> scroller_;
1428 };
1429
1430 SINGLE_AND_MULTI_THREAD_TEST_F(
1431 LayerTreeHostScrollTestScrollZeroMaxScrollOffset);
1432
1433 class LayerTreeHostScrollTestScrollNonDrawnLayer
1434 : public LayerTreeHostScrollTest {
1435 public:
1436 LayerTreeHostScrollTestScrollNonDrawnLayer() = default;
1437
BeginTest()1438 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1439
SetupTree()1440 void SetupTree() override {
1441 LayerTreeHostScrollTest::SetupTree();
1442 layer_tree_host()->OuterViewportScrollLayerForTesting()->SetIsDrawable(
1443 false);
1444 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
1445 gfx::ScrollOffset(20.f, 20.f));
1446 layer_tree_host()
1447 ->OuterViewportScrollLayerForTesting()
1448 ->SetNonFastScrollableRegion(gfx::Rect(20, 20, 20, 20));
1449 }
1450
DrawLayersOnThread(LayerTreeHostImpl * impl)1451 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1452 // Verify that the scroll layer's scroll offset is taken into account when
1453 // checking whether the screen space point is inside the non-fast
1454 // scrollable region.
1455 InputHandler::ScrollStatus status = impl->ScrollBegin(
1456 BeginState(gfx::Point(0, 0)).get(), ScrollInputType::kTouchscreen);
1457 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
1458 EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
1459 status.main_thread_scrolling_reasons);
1460
1461 status = impl->ScrollBegin(BeginState(gfx::Point(21, 21)).get(),
1462 ScrollInputType::kTouchscreen);
1463 EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
1464 EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
1465 status.main_thread_scrolling_reasons);
1466
1467 EndTest();
1468 }
1469 };
1470
1471 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollNonDrawnLayer);
1472
1473 class LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent
1474 : public LayerTreeHostScrollTest {
1475 public:
LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent()1476 LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent() {
1477 SetUseLayerLists();
1478 }
1479
BeginTest()1480 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1481
SetupTree()1482 void SetupTree() override {
1483 LayerTreeHostScrollTest::SetupTree();
1484 GetScrollNode(layer_tree_host()->InnerViewportScrollLayerForTesting())
1485 ->main_thread_scrolling_reasons =
1486 MainThreadScrollingReason::kScrollbarScrolling;
1487 }
1488
DrawLayersOnThread(LayerTreeHostImpl * impl)1489 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1490 LayerImpl* inner_scroll_layer =
1491 impl->active_tree()->InnerViewportScrollLayerForTesting();
1492 LayerImpl* outer_scroll_layer =
1493 impl->active_tree()->OuterViewportScrollLayerForTesting();
1494
1495 ScrollTree& scroll_tree =
1496 impl->active_tree()->property_trees()->scroll_tree;
1497 ScrollNode* inner_scroll_node =
1498 scroll_tree.Node(inner_scroll_layer->scroll_tree_index());
1499 ScrollNode* outer_scroll_node =
1500 scroll_tree.Node(outer_scroll_layer->scroll_tree_index());
1501
1502 InputHandler::ScrollStatus status =
1503 impl->TryScroll(scroll_tree, inner_scroll_node);
1504 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, status.thread);
1505 EXPECT_EQ(MainThreadScrollingReason::kScrollbarScrolling,
1506 status.main_thread_scrolling_reasons);
1507
1508 status = impl->TryScroll(scroll_tree, outer_scroll_node);
1509 EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, status.thread);
1510 EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
1511 status.main_thread_scrolling_reasons);
1512 EndTest();
1513 }
1514 };
1515
1516 SINGLE_AND_MULTI_THREAD_TEST_F(
1517 LayerTreeHostScrollTestImplScrollUnderMainThreadScrollingParent);
1518
1519 class ThreadCheckingInputHandlerClient : public InputHandlerClient {
1520 public:
ThreadCheckingInputHandlerClient(base::SingleThreadTaskRunner * runner,bool * received_stop_flinging)1521 ThreadCheckingInputHandlerClient(base::SingleThreadTaskRunner* runner,
1522 bool* received_stop_flinging)
1523 : task_runner_(runner), received_stop_flinging_(received_stop_flinging) {}
1524
WillShutdown()1525 void WillShutdown() override {
1526 if (!received_stop_flinging_)
1527 ADD_FAILURE() << "WillShutdown() called before fling stopped";
1528 }
1529
Animate(base::TimeTicks time)1530 void Animate(base::TimeTicks time) override {
1531 if (!task_runner_->BelongsToCurrentThread())
1532 ADD_FAILURE() << "Animate called on wrong thread";
1533 }
1534
ReconcileElasticOverscrollAndRootScroll()1535 void ReconcileElasticOverscrollAndRootScroll() override {
1536 if (!task_runner_->BelongsToCurrentThread()) {
1537 ADD_FAILURE() << "ReconcileElasticOverscrollAndRootScroll called on "
1538 << "wrong thread";
1539 }
1540 }
1541
UpdateRootLayerStateForSynchronousInputHandler(const gfx::ScrollOffset & total_scroll_offset,const gfx::ScrollOffset & max_scroll_offset,const gfx::SizeF & scrollable_size,float page_scale_factor,float min_page_scale_factor,float max_page_scale_factor)1542 void UpdateRootLayerStateForSynchronousInputHandler(
1543 const gfx::ScrollOffset& total_scroll_offset,
1544 const gfx::ScrollOffset& max_scroll_offset,
1545 const gfx::SizeF& scrollable_size,
1546 float page_scale_factor,
1547 float min_page_scale_factor,
1548 float max_page_scale_factor) override {
1549 if (!task_runner_->BelongsToCurrentThread()) {
1550 ADD_FAILURE() << "UpdateRootLayerStateForSynchronousInputHandler called "
1551 << " on wrong thread";
1552 }
1553 }
1554
DeliverInputForBeginFrame(const viz::BeginFrameArgs & args)1555 void DeliverInputForBeginFrame(const viz::BeginFrameArgs& args) override {
1556 if (!task_runner_->BelongsToCurrentThread()) {
1557 ADD_FAILURE() << "DeliverInputForBeginFrame called on wrong thread";
1558 }
1559 }
1560
DeliverInputForHighLatencyMode()1561 void DeliverInputForHighLatencyMode() override {
1562 if (!task_runner_->BelongsToCurrentThread()) {
1563 ADD_FAILURE() << "DeliverInputForHighLatencyMode called on wrong thread";
1564 }
1565 }
1566
1567 private:
1568 base::SingleThreadTaskRunner* task_runner_;
1569 bool* received_stop_flinging_;
1570 };
1571
1572 class LayerTreeHostScrollTestLayerStructureChange
1573 : public LayerTreeHostScrollTest {
1574 public:
LayerTreeHostScrollTestLayerStructureChange()1575 LayerTreeHostScrollTestLayerStructureChange()
1576 : scroll_destroy_whole_tree_(false) {}
1577
SetupTree()1578 void SetupTree() override {
1579 LayerTreeHostScrollTest::SetupTree();
1580 Layer* root_layer = layer_tree_host()->root_layer();
1581 Layer* outer_scroll_layer =
1582 layer_tree_host()->OuterViewportScrollLayerForTesting();
1583
1584 Layer* root_scroll_layer = CreateScrollLayer(outer_scroll_layer);
1585 Layer* sibling_scroll_layer = CreateScrollLayer(outer_scroll_layer);
1586 Layer* child_scroll_layer = CreateScrollLayer(root_scroll_layer);
1587 root_scroll_layer_id_ = root_scroll_layer->id();
1588 sibling_scroll_layer_id_ = sibling_scroll_layer->id();
1589 child_scroll_layer_id_ = child_scroll_layer->id();
1590 fake_content_layer_client_.set_bounds(root_layer->bounds());
1591 }
1592
BeginTest()1593 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
1594
DrawLayersOnThread(LayerTreeHostImpl * impl)1595 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1596 switch (impl->active_tree()->source_frame_number()) {
1597 case 0:
1598 SetScrollOffsetDelta(
1599 impl->active_tree()->LayerById(root_scroll_layer_id_),
1600 gfx::Vector2dF(5, 5));
1601 SetScrollOffsetDelta(
1602 impl->active_tree()->LayerById(child_scroll_layer_id_),
1603 gfx::Vector2dF(5, 5));
1604 SetScrollOffsetDelta(
1605 impl->active_tree()->LayerById(sibling_scroll_layer_id_),
1606 gfx::Vector2dF(5, 5));
1607 PostSetNeedsCommitToMainThread();
1608 break;
1609 case 1:
1610 EndTest();
1611 break;
1612 }
1613 }
1614
DidScroll(ElementId element_id,const gfx::ScrollOffset &,const base::Optional<TargetSnapAreaElementIds> &)1615 void DidScroll(ElementId element_id,
1616 const gfx::ScrollOffset&,
1617 const base::Optional<TargetSnapAreaElementIds>&) override {
1618 if (scroll_destroy_whole_tree_) {
1619 layer_tree_host()->SetRootLayer(nullptr);
1620 layer_tree_host()->property_trees()->clear();
1621 layer_tree_host()->RegisterViewportPropertyIds(
1622 LayerTreeHost::ViewportPropertyIds());
1623 EndTest();
1624 return;
1625 }
1626 layer_tree_host()->LayerByElementId(element_id)->RemoveFromParent();
1627 }
1628
1629 protected:
CreateScrollLayer(Layer * parent)1630 Layer* CreateScrollLayer(Layer* parent) {
1631 scoped_refptr<PictureLayer> scroll_layer =
1632 PictureLayer::Create(&fake_content_layer_client_);
1633 scroll_layer->SetIsDrawable(true);
1634 scroll_layer->SetHitTestable(true);
1635 scroll_layer->SetElementId(
1636 LayerIdToElementIdForTesting(scroll_layer->id()));
1637 scroll_layer->SetBounds(gfx::Size(parent->bounds().width() + 100,
1638 parent->bounds().height() + 100));
1639
1640 CopyProperties(parent, scroll_layer.get());
1641 CreateTransformNode(scroll_layer.get());
1642 CreateScrollNode(scroll_layer.get(), parent->bounds());
1643 layer_tree_host()->root_layer()->AddChild(scroll_layer);
1644
1645 return scroll_layer.get();
1646 }
1647
SetScrollOffsetDelta(LayerImpl * layer_impl,const gfx::Vector2dF & delta)1648 static void SetScrollOffsetDelta(LayerImpl* layer_impl,
1649 const gfx::Vector2dF& delta) {
1650 if (layer_impl->layer_tree_impl()
1651 ->property_trees()
1652 ->scroll_tree.SetScrollOffsetDeltaForTesting(
1653 layer_impl->element_id(), delta))
1654 layer_impl->layer_tree_impl()->DidUpdateScrollOffset(
1655 layer_impl->element_id());
1656 }
1657
1658 int root_scroll_layer_id_;
1659 int sibling_scroll_layer_id_;
1660 int child_scroll_layer_id_;
1661
1662 FakeContentLayerClient fake_content_layer_client_;
1663
1664 bool scroll_destroy_whole_tree_;
1665 };
1666
TEST_F(LayerTreeHostScrollTestLayerStructureChange,ScrollDestroyLayer)1667 TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyLayer) {
1668 RunTest(CompositorMode::THREADED);
1669 }
1670
TEST_F(LayerTreeHostScrollTestLayerStructureChange,ScrollDestroyWholeTree)1671 TEST_F(LayerTreeHostScrollTestLayerStructureChange, ScrollDestroyWholeTree) {
1672 scroll_destroy_whole_tree_ = true;
1673 RunTest(CompositorMode::THREADED);
1674 }
1675
1676 class LayerTreeHostScrollTestScrollMFBA : public LayerTreeHostScrollTest {
1677 public:
LayerTreeHostScrollTestScrollMFBA()1678 LayerTreeHostScrollTestScrollMFBA()
1679 : initial_scroll_(10, 20),
1680 second_scroll_(40, 5),
1681 third_scroll_(20, 10),
1682 scroll_amount_(2, -1),
1683 num_commits_(0) {}
1684
InitializeSettings(LayerTreeSettings * settings)1685 void InitializeSettings(LayerTreeSettings* settings) override {
1686 LayerTreeHostScrollTest::InitializeSettings(settings);
1687 settings->main_frame_before_activation_enabled = true;
1688 }
1689
BeginTest()1690 void BeginTest() override {
1691 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
1692 initial_scroll_);
1693 PostSetNeedsCommitToMainThread();
1694 }
1695
ReadyToCommitOnThread(LayerTreeHostImpl * impl)1696 void ReadyToCommitOnThread(LayerTreeHostImpl* impl) override {
1697 switch (num_commits_) {
1698 case 1:
1699 // Ask for commit here because activation (and draw) will be blocked.
1700 impl->SetNeedsCommit();
1701 // Block activation after second commit until third commit is ready.
1702 impl->BlockNotifyReadyToActivateForTesting(true);
1703 break;
1704 case 2:
1705 // Unblock activation after third commit is ready.
1706 impl->BlockNotifyReadyToActivateForTesting(false);
1707 break;
1708 }
1709 num_commits_++;
1710 }
1711
UpdateLayerTreeHost()1712 void UpdateLayerTreeHost() override {
1713 Layer* scroll_layer =
1714 layer_tree_host()->OuterViewportScrollLayerForTesting();
1715 switch (layer_tree_host()->SourceFrameNumber()) {
1716 case 0:
1717 EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer));
1718 break;
1719 case 1:
1720 EXPECT_VECTOR_EQ(
1721 gfx::ScrollOffsetWithDelta(initial_scroll_, scroll_amount_),
1722 CurrentScrollOffset(scroll_layer));
1723 // Pretend like Javascript updated the scroll position itself.
1724 SetScrollOffset(scroll_layer, second_scroll_);
1725 break;
1726 case 2:
1727 // Third frame does not see a scroll delta because we only did one
1728 // scroll for the second and third frames.
1729 EXPECT_VECTOR_EQ(second_scroll_, CurrentScrollOffset(scroll_layer));
1730 // Pretend like Javascript updated the scroll position itself.
1731 SetScrollOffset(scroll_layer, third_scroll_);
1732 break;
1733 }
1734 }
1735
DrawLayersOnThread(LayerTreeHostImpl * impl)1736 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1737 LayerImpl* scroll_layer =
1738 impl->active_tree()->OuterViewportScrollLayerForTesting();
1739 switch (impl->active_tree()->source_frame_number()) {
1740 case 0:
1741 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer));
1742 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
1743 Scroll(impl);
1744 EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer));
1745 // Ask for commit after we've scrolled.
1746 impl->SetNeedsCommit();
1747 break;
1748 case 1:
1749 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(scroll_layer));
1750 EXPECT_VECTOR_EQ(second_scroll_, ScrollOffsetBase(scroll_layer));
1751 Scroll(impl);
1752 EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer));
1753 break;
1754 case 2:
1755 // The scroll hasn't been consumed by the main thread.
1756 EXPECT_VECTOR_EQ(scroll_amount_, ScrollDelta(scroll_layer));
1757 EXPECT_VECTOR_EQ(third_scroll_, ScrollOffsetBase(scroll_layer));
1758 EndTest();
1759 break;
1760 }
1761 }
1762
AfterTest()1763 void AfterTest() override {
1764 EXPECT_EQ(3, num_commits_);
1765 EXPECT_EQ(1, num_outer_viewport_scrolls_);
1766 }
1767
1768 private:
Scroll(LayerTreeHostImpl * impl)1769 void Scroll(LayerTreeHostImpl* impl) {
1770 LayerImpl* root = impl->active_tree()->root_layer();
1771 LayerImpl* scroll_layer =
1772 impl->active_tree()->OuterViewportScrollLayerForTesting();
1773
1774 scroll_layer->SetBounds(
1775 gfx::Size(root->bounds().width() + 100, root->bounds().height() + 100));
1776 scroll_layer->ScrollBy(scroll_amount_);
1777 }
1778
1779 gfx::ScrollOffset initial_scroll_;
1780 gfx::ScrollOffset second_scroll_;
1781 gfx::ScrollOffset third_scroll_;
1782 gfx::Vector2dF scroll_amount_;
1783 int num_commits_;
1784 };
1785
1786 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollMFBA);
1787
1788 class LayerTreeHostScrollTestScrollAbortedCommitMFBA
1789 : public LayerTreeHostScrollTest {
1790 public:
LayerTreeHostScrollTestScrollAbortedCommitMFBA()1791 LayerTreeHostScrollTestScrollAbortedCommitMFBA()
1792 : initial_scroll_(50, 60),
1793 impl_scroll_(-3, 2),
1794 second_main_scroll_(14, -3),
1795 num_will_begin_main_frames_(0),
1796 num_did_begin_main_frames_(0),
1797 num_will_commits_(0),
1798 num_did_commits_(0),
1799 num_impl_commits_(0),
1800 num_aborted_commits_(0),
1801 num_draws_(0) {}
1802
InitializeSettings(LayerTreeSettings * settings)1803 void InitializeSettings(LayerTreeSettings* settings) override {
1804 LayerTreeHostScrollTest::InitializeSettings(settings);
1805 settings->main_frame_before_activation_enabled = true;
1806 }
1807
BeginTest()1808 void BeginTest() override {
1809 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
1810 initial_scroll_);
1811 PostSetNeedsCommitToMainThread();
1812 }
1813
SetupTree()1814 void SetupTree() override {
1815 LayerTreeHostScrollTest::SetupTree();
1816
1817 gfx::Size scroll_layer_bounds(200, 200);
1818 layer_tree_host()->OuterViewportScrollLayerForTesting()->SetBounds(
1819 scroll_layer_bounds);
1820 layer_tree_host()->SetPageScaleFactorAndLimits(1.f, 0.01f, 100.f);
1821 }
1822
WillBeginMainFrame()1823 void WillBeginMainFrame() override {
1824 num_will_begin_main_frames_++;
1825 Layer* root_scroll_layer =
1826 layer_tree_host()->OuterViewportScrollLayerForTesting();
1827 switch (num_will_begin_main_frames_) {
1828 case 1:
1829 // This will not be aborted because of the initial prop changes.
1830 EXPECT_EQ(0, num_outer_viewport_scrolls_);
1831 EXPECT_EQ(0, layer_tree_host()->SourceFrameNumber());
1832 EXPECT_VECTOR_EQ(initial_scroll_,
1833 CurrentScrollOffset(root_scroll_layer));
1834 break;
1835 case 2:
1836 // This commit will not be aborted because of the scroll change.
1837 EXPECT_EQ(1, num_outer_viewport_scrolls_);
1838 EXPECT_EQ(1, layer_tree_host()->SourceFrameNumber());
1839 EXPECT_VECTOR_EQ(
1840 gfx::ScrollOffsetWithDelta(initial_scroll_, impl_scroll_),
1841 CurrentScrollOffset(root_scroll_layer));
1842 SetScrollOffset(
1843 root_scroll_layer,
1844 gfx::ScrollOffsetWithDelta(CurrentScrollOffset(root_scroll_layer),
1845 second_main_scroll_));
1846 break;
1847 case 3: {
1848 // This commit will be aborted.
1849 EXPECT_EQ(2, num_outer_viewport_scrolls_);
1850 // The source frame number still increases even with the abort.
1851 EXPECT_EQ(2, layer_tree_host()->SourceFrameNumber());
1852 gfx::Vector2dF delta =
1853 impl_scroll_ + impl_scroll_ + second_main_scroll_;
1854 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
1855 CurrentScrollOffset(root_scroll_layer));
1856 break;
1857 }
1858 case 4: {
1859 // This commit will also be aborted.
1860 EXPECT_EQ(3, num_outer_viewport_scrolls_);
1861 EXPECT_EQ(3, layer_tree_host()->SourceFrameNumber());
1862 gfx::Vector2dF delta =
1863 impl_scroll_ + impl_scroll_ + impl_scroll_ + second_main_scroll_;
1864 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
1865 CurrentScrollOffset(root_scroll_layer));
1866 break;
1867 }
1868 }
1869 }
1870
DidBeginMainFrame()1871 void DidBeginMainFrame() override { num_did_begin_main_frames_++; }
1872
WillCommit()1873 void WillCommit() override { num_will_commits_++; }
1874
DidCommit()1875 void DidCommit() override { num_did_commits_++; }
1876
BeginCommitOnThread(LayerTreeHostImpl * impl)1877 void BeginCommitOnThread(LayerTreeHostImpl* impl) override {
1878 switch (num_impl_commits_) {
1879 case 1:
1880 // Redraw so that we keep scrolling.
1881 impl->SetNeedsRedraw();
1882 // Block activation until third commit is aborted.
1883 impl->BlockNotifyReadyToActivateForTesting(true);
1884 break;
1885 }
1886 num_impl_commits_++;
1887 }
1888
BeginMainFrameAbortedOnThread(LayerTreeHostImpl * impl,CommitEarlyOutReason reason)1889 void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* impl,
1890 CommitEarlyOutReason reason) override {
1891 switch (num_aborted_commits_) {
1892 case 0:
1893 EXPECT_EQ(2, num_impl_commits_);
1894 // Unblock activation when third commit is aborted.
1895 impl->BlockNotifyReadyToActivateForTesting(false);
1896 break;
1897 case 1:
1898 EXPECT_EQ(2, num_impl_commits_);
1899 // Redraw to end the test.
1900 impl->SetNeedsRedraw();
1901 break;
1902 }
1903 num_aborted_commits_++;
1904 }
1905
DrawLayersOnThread(LayerTreeHostImpl * impl)1906 void DrawLayersOnThread(LayerTreeHostImpl* impl) override {
1907 LayerImpl* root_scroll_layer =
1908 impl->active_tree()->OuterViewportScrollLayerForTesting();
1909 switch (impl->active_tree()->source_frame_number()) {
1910 case 0: {
1911 switch (num_impl_commits_) {
1912 case 1: {
1913 // First draw
1914 EXPECT_VECTOR_EQ(gfx::Vector2d(), ScrollDelta(root_scroll_layer));
1915 root_scroll_layer->ScrollBy(impl_scroll_);
1916 EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer));
1917 EXPECT_VECTOR_EQ(initial_scroll_,
1918 ScrollOffsetBase(root_scroll_layer));
1919 impl->SetNeedsCommit();
1920 break;
1921 }
1922 case 2: {
1923 // Second draw but no new active tree because activation is blocked.
1924 EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer));
1925 root_scroll_layer->ScrollBy(impl_scroll_);
1926 EXPECT_VECTOR_EQ(impl_scroll_ + impl_scroll_,
1927 ScrollDelta(root_scroll_layer));
1928 EXPECT_VECTOR_EQ(initial_scroll_,
1929 ScrollOffsetBase(root_scroll_layer));
1930 // Ask for another commit (which will abort).
1931 impl->SetNeedsCommit();
1932 break;
1933 }
1934 default:
1935 NOTREACHED();
1936 }
1937 break;
1938 }
1939 case 1: {
1940 EXPECT_EQ(2, num_impl_commits_);
1941 // All scroll deltas so far should be consumed.
1942 EXPECT_EQ(gfx::ScrollOffset(), ScrollDelta(root_scroll_layer));
1943 switch (num_aborted_commits_) {
1944 case 1: {
1945 root_scroll_layer->ScrollBy(impl_scroll_);
1946 EXPECT_VECTOR_EQ(impl_scroll_, ScrollDelta(root_scroll_layer));
1947 gfx::Vector2dF prev_delta =
1948 impl_scroll_ + impl_scroll_ + second_main_scroll_;
1949 EXPECT_VECTOR_EQ(
1950 gfx::ScrollOffsetWithDelta(initial_scroll_, prev_delta),
1951 ScrollOffsetBase(root_scroll_layer));
1952 // Ask for another commit (which will abort).
1953 impl->SetNeedsCommit();
1954 break;
1955 }
1956 case 2: {
1957 gfx::Vector2dF delta = impl_scroll_ + impl_scroll_ + impl_scroll_ +
1958 second_main_scroll_;
1959 EXPECT_VECTOR_EQ(gfx::ScrollOffsetWithDelta(initial_scroll_, delta),
1960 ScrollOffsetBase(root_scroll_layer));
1961 // End test after second aborted commit (fourth commit request).
1962 EndTest();
1963 break;
1964 }
1965 }
1966 break;
1967 }
1968 }
1969 num_draws_++;
1970 }
1971
AfterTest()1972 void AfterTest() override {
1973 EXPECT_EQ(3, num_outer_viewport_scrolls_);
1974 // Verify that the embedder sees aborted commits as real commits.
1975 EXPECT_EQ(4, num_will_begin_main_frames_);
1976 EXPECT_EQ(4, num_did_begin_main_frames_);
1977 EXPECT_EQ(4, num_will_commits_);
1978 EXPECT_EQ(4, num_did_commits_);
1979 // ...but the compositor thread only sees two real ones.
1980 EXPECT_EQ(2, num_impl_commits_);
1981 // ...and two aborted ones.
1982 EXPECT_EQ(2, num_aborted_commits_);
1983 // ...and four draws.
1984 EXPECT_EQ(4, num_draws_);
1985 }
1986
1987 private:
1988 gfx::ScrollOffset initial_scroll_;
1989 gfx::Vector2dF impl_scroll_;
1990 gfx::Vector2dF second_main_scroll_;
1991 int num_will_begin_main_frames_;
1992 int num_did_begin_main_frames_;
1993 int num_will_commits_;
1994 int num_did_commits_;
1995 int num_impl_commits_;
1996 int num_aborted_commits_;
1997 int num_draws_;
1998 };
1999
2000 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestScrollAbortedCommitMFBA);
2001
2002 class MockInputHandlerClient : public InputHandlerClient {
2003 public:
2004 MockInputHandlerClient() = default;
2005
2006 MOCK_METHOD0(ReconcileElasticOverscrollAndRootScroll, void());
2007
WillShutdown()2008 void WillShutdown() override {}
Animate(base::TimeTicks)2009 void Animate(base::TimeTicks) override {}
UpdateRootLayerStateForSynchronousInputHandler(const gfx::ScrollOffset & total_scroll_offset,const gfx::ScrollOffset & max_scroll_offset,const gfx::SizeF & scrollable_size,float page_scale_factor,float min_page_scale_factor,float max_page_scale_factor)2010 void UpdateRootLayerStateForSynchronousInputHandler(
2011 const gfx::ScrollOffset& total_scroll_offset,
2012 const gfx::ScrollOffset& max_scroll_offset,
2013 const gfx::SizeF& scrollable_size,
2014 float page_scale_factor,
2015 float min_page_scale_factor,
2016 float max_page_scale_factor) override {}
DeliverInputForBeginFrame(const viz::BeginFrameArgs & args)2017 void DeliverInputForBeginFrame(const viz::BeginFrameArgs& args) override {}
DeliverInputForHighLatencyMode()2018 void DeliverInputForHighLatencyMode() override {}
2019 };
2020
2021 // This is a regression test, see crbug.com/639046.
2022 class LayerTreeHostScrollTestElasticOverscroll
2023 : public LayerTreeHostScrollTest {
2024 public:
LayerTreeHostScrollTestElasticOverscroll()2025 LayerTreeHostScrollTestElasticOverscroll()
2026 : num_begin_main_frames_impl_thread_(0),
2027 scroll_elasticity_helper_(nullptr),
2028 num_begin_main_frames_main_thread_(0) {}
2029
InitializeSettings(LayerTreeSettings * settings)2030 void InitializeSettings(LayerTreeSettings* settings) override {
2031 LayerTreeHostScrollTest::InitializeSettings(settings);
2032 settings->enable_elastic_overscroll = true;
2033 }
2034
BeginTest()2035 void BeginTest() override {
2036 DCHECK(HasImplThread());
2037 ImplThreadTaskRunner()->PostTask(
2038 FROM_HERE,
2039 base::BindOnce(
2040 &LayerTreeHostScrollTestElasticOverscroll::BindInputHandler,
2041 base::Unretained(this), layer_tree_host()->GetInputHandler()));
2042 PostSetNeedsCommitToMainThread();
2043 }
2044
BindInputHandler(base::WeakPtr<InputHandler> input_handler)2045 void BindInputHandler(base::WeakPtr<InputHandler> input_handler) {
2046 DCHECK(task_runner_provider()->IsImplThread());
2047 input_handler->BindToClient(&input_handler_client_);
2048 scroll_elasticity_helper_ = input_handler->CreateScrollElasticityHelper();
2049 DCHECK(scroll_elasticity_helper_);
2050 }
2051
ApplyViewportChanges(const ApplyViewportChangesArgs & args)2052 void ApplyViewportChanges(const ApplyViewportChangesArgs& args) override {
2053 DCHECK_NE(0, num_begin_main_frames_main_thread_)
2054 << "The first BeginMainFrame has no deltas to report";
2055 DCHECK_LT(num_begin_main_frames_main_thread_, 5);
2056
2057 gfx::Vector2dF expected_elastic_overscroll =
2058 elastic_overscroll_test_cases_[num_begin_main_frames_main_thread_];
2059 current_elastic_overscroll_ += args.elastic_overscroll_delta;
2060 EXPECT_EQ(expected_elastic_overscroll, current_elastic_overscroll_);
2061 EXPECT_EQ(expected_elastic_overscroll,
2062 layer_tree_host()->elastic_overscroll());
2063 }
2064
WillBeginMainFrame()2065 void WillBeginMainFrame() override { num_begin_main_frames_main_thread_++; }
2066
BeginMainFrameAbortedOnThread(LayerTreeHostImpl * host_impl,CommitEarlyOutReason reason)2067 void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
2068 CommitEarlyOutReason reason) override {
2069 VerifyBeginMainFrameResultOnImplThread(host_impl, true);
2070 }
2071
WillCommitCompleteOnThread(LayerTreeHostImpl * host_impl)2072 void WillCommitCompleteOnThread(LayerTreeHostImpl* host_impl) override {
2073 VerifyBeginMainFrameResultOnImplThread(host_impl, false);
2074 }
2075
VerifyBeginMainFrameResultOnImplThread(LayerTreeHostImpl * host_impl,bool begin_main_frame_aborted)2076 void VerifyBeginMainFrameResultOnImplThread(LayerTreeHostImpl* host_impl,
2077 bool begin_main_frame_aborted) {
2078 gfx::Vector2dF expected_elastic_overscroll =
2079 elastic_overscroll_test_cases_[num_begin_main_frames_impl_thread_];
2080 EXPECT_EQ(expected_elastic_overscroll,
2081 scroll_elasticity_helper_->StretchAmount());
2082 if (!begin_main_frame_aborted)
2083 EXPECT_EQ(
2084 expected_elastic_overscroll,
2085 host_impl->pending_tree()->elastic_overscroll()->Current(false));
2086
2087 ++num_begin_main_frames_impl_thread_;
2088 gfx::Vector2dF next_test_case;
2089 if (num_begin_main_frames_impl_thread_ < 5)
2090 next_test_case =
2091 elastic_overscroll_test_cases_[num_begin_main_frames_impl_thread_];
2092
2093 switch (num_begin_main_frames_impl_thread_) {
2094 case 1:
2095 // The first BeginMainFrame is never aborted.
2096 EXPECT_FALSE(begin_main_frame_aborted);
2097 scroll_elasticity_helper_->SetStretchAmount(next_test_case);
2098 break;
2099 case 2:
2100 EXPECT_TRUE(begin_main_frame_aborted);
2101 scroll_elasticity_helper_->SetStretchAmount(next_test_case);
2102
2103 // Since the elastic overscroll is never mutated on the main thread, the
2104 // BeginMainFrame which reports the delta is aborted. Post a commit
2105 // request to the main thread to make sure it goes through.
2106 PostSetNeedsCommitToMainThread();
2107 break;
2108 case 3:
2109 EXPECT_FALSE(begin_main_frame_aborted);
2110 scroll_elasticity_helper_->SetStretchAmount(next_test_case);
2111 PostSetNeedsCommitToMainThread();
2112 break;
2113 case 4:
2114 EXPECT_FALSE(begin_main_frame_aborted);
2115 scroll_elasticity_helper_->SetStretchAmount(next_test_case);
2116 break;
2117 case 5:
2118 EXPECT_TRUE(begin_main_frame_aborted);
2119 EndTest();
2120 break;
2121 default:
2122 NOTREACHED();
2123 }
2124 }
2125
DidActivateTreeOnThread(LayerTreeHostImpl * host_impl)2126 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
2127 if (num_begin_main_frames_impl_thread_ == 5)
2128 return;
2129
2130 // Ensure that the elastic overscroll value on the active tree remains
2131 // unmodified after activation.
2132 gfx::Vector2dF expected_elastic_overscroll =
2133 elastic_overscroll_test_cases_[num_begin_main_frames_impl_thread_];
2134 EXPECT_EQ(expected_elastic_overscroll,
2135 scroll_elasticity_helper_->StretchAmount());
2136 }
2137
WillPrepareToDrawOnThread(LayerTreeHostImpl * host_impl)2138 void WillPrepareToDrawOnThread(LayerTreeHostImpl* host_impl) override {
2139 // The InputHandlerClient must receive a call to reconcile the overscroll
2140 // before each draw.
2141 EXPECT_CALL(input_handler_client_,
2142 ReconcileElasticOverscrollAndRootScroll())
2143 .Times(1);
2144 }
2145
PrepareToDrawOnThread(LayerTreeHostImpl * host_impl,LayerTreeHostImpl::FrameData * frame_data,DrawResult draw_result)2146 DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl,
2147 LayerTreeHostImpl::FrameData* frame_data,
2148 DrawResult draw_result) override {
2149 Mock::VerifyAndClearExpectations(&input_handler_client_);
2150 return draw_result;
2151 }
2152
AfterTest()2153 void AfterTest() override {
2154 EXPECT_EQ(num_begin_main_frames_impl_thread_, 5);
2155 EXPECT_EQ(num_begin_main_frames_main_thread_, 5);
2156 gfx::Vector2dF expected_elastic_overscroll =
2157 elastic_overscroll_test_cases_[4];
2158 EXPECT_EQ(expected_elastic_overscroll, current_elastic_overscroll_);
2159 }
2160
2161 private:
2162 // These values should be used on the impl thread only.
2163 int num_begin_main_frames_impl_thread_;
2164 MockInputHandlerClient input_handler_client_;
2165 ScrollElasticityHelper* scroll_elasticity_helper_;
2166
2167 // These values should be used on the main thread only.
2168 int num_begin_main_frames_main_thread_;
2169 gfx::Vector2dF current_elastic_overscroll_;
2170
2171 const gfx::Vector2dF elastic_overscroll_test_cases_[5] = {
2172 gfx::Vector2dF(0, 0), gfx::Vector2dF(5, 10), gfx::Vector2dF(5, 5),
2173 gfx::Vector2dF(-4, -5), gfx::Vector2dF(0, 0)};
2174 };
2175
2176 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestElasticOverscroll);
2177
2178 class LayerTreeHostScrollTestPropertyTreeUpdate
2179 : public LayerTreeHostScrollTest {
2180 public:
LayerTreeHostScrollTestPropertyTreeUpdate()2181 LayerTreeHostScrollTestPropertyTreeUpdate()
2182 : initial_scroll_(10, 20), second_scroll_(0, 0) {}
2183
BeginTest()2184 void BeginTest() override {
2185 SetScrollOffset(layer_tree_host()->OuterViewportScrollLayerForTesting(),
2186 initial_scroll_);
2187 PostSetNeedsCommitToMainThread();
2188 }
2189
UpdateLayerTreeHost()2190 void UpdateLayerTreeHost() override {
2191 Layer* scroll_layer =
2192 layer_tree_host()->OuterViewportScrollLayerForTesting();
2193 if (layer_tree_host()->SourceFrameNumber() == 0) {
2194 EXPECT_VECTOR_EQ(initial_scroll_, CurrentScrollOffset(scroll_layer));
2195 } else {
2196 EXPECT_VECTOR_EQ(
2197 gfx::ScrollOffsetWithDelta(initial_scroll_, scroll_amount_),
2198 CurrentScrollOffset(scroll_layer));
2199 SetScrollOffset(scroll_layer, second_scroll_);
2200 SetOpacity(scroll_layer, 0.5f);
2201 }
2202 }
2203
DidActivateTreeOnThread(LayerTreeHostImpl * impl)2204 void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
2205 LayerImpl* scroll_layer =
2206 impl->active_tree()->OuterViewportScrollLayerForTesting();
2207
2208 switch (impl->active_tree()->source_frame_number()) {
2209 case 0:
2210 EXPECT_VECTOR_EQ(initial_scroll_, ScrollOffsetBase(scroll_layer));
2211 EXPECT_VECTOR_EQ(initial_scroll_,
2212 GetTransformNode(scroll_layer)->scroll_offset);
2213 PostSetNeedsCommitToMainThread();
2214 break;
2215 case 1:
2216 EXPECT_VECTOR_EQ(second_scroll_, ScrollOffsetBase(scroll_layer));
2217 EXPECT_VECTOR_EQ(second_scroll_,
2218 GetTransformNode(scroll_layer)->scroll_offset);
2219 EndTest();
2220 break;
2221 }
2222 }
2223
2224 private:
2225 gfx::ScrollOffset initial_scroll_;
2226 gfx::ScrollOffset second_scroll_;
2227 gfx::Vector2dF scroll_amount_;
2228 };
2229
2230 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostScrollTestPropertyTreeUpdate);
2231
2232 class LayerTreeHostScrollTestImplSideInvalidation
2233 : public LayerTreeHostScrollTest {
BeginTest()2234 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
2235
DidScrollOuterViewport(const gfx::ScrollOffset & offset)2236 void DidScrollOuterViewport(const gfx::ScrollOffset& offset) override {
2237 LayerTreeHostScrollTest::DidScrollOuterViewport(offset);
2238
2239 // Defer responding to the main frame until an impl-side pending tree is
2240 // created for the invalidation request.
2241 {
2242 CompletionEvent completion;
2243 task_runner_provider()->ImplThreadTaskRunner()->PostTask(
2244 FROM_HERE,
2245 base::BindOnce(&LayerTreeHostScrollTestImplSideInvalidation::
2246 WaitForInvalidationOnImplThread,
2247 base::Unretained(this), &completion));
2248 completion.Wait();
2249 }
2250
2251 switch (++num_of_deltas_) {
2252 case 1: {
2253 // First set of deltas is here. The impl thread will scroll to the
2254 // second case on activation, so add a delta from the main thread that
2255 // takes us to the final value.
2256 Layer* outer_viewport_layer =
2257 layer_tree_host()->OuterViewportScrollLayerForTesting();
2258 gfx::ScrollOffset delta_to_send =
2259 outer_viewport_offsets_[2] - outer_viewport_offsets_[1];
2260 SetScrollOffset(
2261 outer_viewport_layer,
2262 CurrentScrollOffset(outer_viewport_layer) + delta_to_send);
2263 } break;
2264 case 2:
2265 // Let the commit abort for the second set of deltas.
2266 break;
2267 default:
2268 NOTREACHED();
2269 }
2270 }
2271
WaitForInvalidationOnImplThread(CompletionEvent * completion)2272 void WaitForInvalidationOnImplThread(CompletionEvent* completion) {
2273 impl_side_invalidation_event_ = completion;
2274 SignalCompletionIfPossible();
2275 }
2276
DidInvalidateContentOnImplSide(LayerTreeHostImpl * host_impl)2277 void DidInvalidateContentOnImplSide(LayerTreeHostImpl* host_impl) override {
2278 invalidated_on_impl_thread_ = true;
2279 SignalCompletionIfPossible();
2280 }
2281
WillNotifyReadyToActivateOnThread(LayerTreeHostImpl * host_impl)2282 void WillNotifyReadyToActivateOnThread(
2283 LayerTreeHostImpl* host_impl) override {
2284 // Ensure that the scroll-offsets on the TransformTree are consistent with
2285 // the synced scroll offsets, for the pending tree.
2286 if (!host_impl->pending_tree())
2287 return;
2288
2289 LayerImpl* scroll_layer =
2290 host_impl->pending_tree()->OuterViewportScrollLayerForTesting();
2291 gfx::ScrollOffset scroll_offset = CurrentScrollOffset(scroll_layer);
2292 int transform_index = scroll_layer->transform_tree_index();
2293 gfx::ScrollOffset transform_tree_scroll_offset =
2294 host_impl->pending_tree()
2295 ->property_trees()
2296 ->transform_tree.Node(transform_index)
2297 ->scroll_offset;
2298 EXPECT_EQ(scroll_offset, transform_tree_scroll_offset);
2299 }
2300
SignalCompletionIfPossible()2301 void SignalCompletionIfPossible() {
2302 if (!invalidated_on_impl_thread_ || !impl_side_invalidation_event_)
2303 return;
2304
2305 impl_side_invalidation_event_->Signal();
2306 impl_side_invalidation_event_ = nullptr;
2307 invalidated_on_impl_thread_ = false;
2308 }
2309
DidSendBeginMainFrameOnThread(LayerTreeHostImpl * host_impl)2310 void DidSendBeginMainFrameOnThread(LayerTreeHostImpl* host_impl) override {
2311 switch (++num_of_main_frames_) {
2312 case 1:
2313 // Do nothing for the first BeginMainFrame.
2314 break;
2315 case 2:
2316 // Add some more delta to the active tree state of the scroll offset and
2317 // a commit to send this additional delta to the main thread.
2318 host_impl->active_tree()
2319 ->OuterViewportScrollLayerForTesting()
2320 ->SetCurrentScrollOffset(outer_viewport_offsets_[1]);
2321 host_impl->SetNeedsCommit();
2322
2323 // Request an impl-side invalidation to create an impl-side pending
2324 // tree.
2325 host_impl->RequestImplSideInvalidationForCheckerImagedTiles();
2326 break;
2327 case 3:
2328 // Request another impl-side invalidation so the aborted commit comes
2329 // after this tree is activated.
2330 host_impl->RequestImplSideInvalidationForCheckerImagedTiles();
2331 break;
2332 default:
2333 NOTREACHED();
2334 }
2335 }
2336
BeginMainFrameAbortedOnThread(LayerTreeHostImpl * host_impl,CommitEarlyOutReason reason)2337 void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* host_impl,
2338 CommitEarlyOutReason reason) override {
2339 EXPECT_EQ(CommitEarlyOutReason::FINISHED_NO_UPDATES, reason);
2340 EXPECT_EQ(3, num_of_main_frames_);
2341 EXPECT_EQ(
2342 outer_viewport_offsets_[2],
2343 CurrentScrollOffset(
2344 host_impl->active_tree()->OuterViewportScrollLayerForTesting()));
2345 }
2346
DidActivateTreeOnThread(LayerTreeHostImpl * host_impl)2347 void DidActivateTreeOnThread(LayerTreeHostImpl* host_impl) override {
2348 switch (++num_of_activations_) {
2349 case 1:
2350 // Now that we have the active tree, scroll a layer and ask for a commit
2351 // to send a BeginMainFrame with the scroll delta to the main thread.
2352 host_impl->active_tree()
2353 ->OuterViewportScrollLayerForTesting()
2354 ->SetCurrentScrollOffset(outer_viewport_offsets_[0]);
2355 host_impl->SetNeedsCommit();
2356 break;
2357 case 2:
2358 // The second activation is from an impl-side pending tree so the source
2359 // frame number on the active tree remains unchanged, and the scroll
2360 // offset on the active tree should also remain unchanged.
2361 EXPECT_EQ(0, host_impl->active_tree()->source_frame_number());
2362 EXPECT_EQ(
2363 outer_viewport_offsets_[1],
2364 CurrentScrollOffset(host_impl->active_tree()
2365 ->OuterViewportScrollLayerForTesting()));
2366 break;
2367 case 3:
2368 // The third activation is from a commit. The scroll offset on the
2369 // active tree should include deltas sent from the main thread.
2370 EXPECT_EQ(1, host_impl->active_tree()->source_frame_number());
2371 EXPECT_EQ(
2372 outer_viewport_offsets_[2],
2373 CurrentScrollOffset(host_impl->active_tree()
2374 ->OuterViewportScrollLayerForTesting()));
2375 break;
2376 case 4:
2377 // The fourth activation is from an impl-side pending tree, which should
2378 // leave the scroll offset unchanged.
2379 EXPECT_EQ(1, host_impl->active_tree()->source_frame_number());
2380 EXPECT_EQ(
2381 outer_viewport_offsets_[2],
2382 CurrentScrollOffset(host_impl->active_tree()
2383 ->OuterViewportScrollLayerForTesting()));
2384 EndTest();
2385 break;
2386 default:
2387 NOTREACHED();
2388 }
2389 }
2390
AfterTest()2391 void AfterTest() override {
2392 EXPECT_EQ(4, num_of_activations_);
2393 EXPECT_EQ(2, num_of_deltas_);
2394 EXPECT_EQ(3, num_of_main_frames_);
2395 }
2396
2397 const gfx::ScrollOffset outer_viewport_offsets_[3] = {
2398 gfx::ScrollOffset(20, 20), gfx::ScrollOffset(50, 50),
2399 gfx::ScrollOffset(70, 70)};
2400
2401 // Impl thread.
2402 int num_of_activations_ = 0;
2403 int num_of_main_frames_ = 0;
2404 bool invalidated_on_impl_thread_ = false;
2405 CompletionEvent* impl_side_invalidation_event_ = nullptr;
2406
2407 // Main thread.
2408 int num_of_deltas_ = 0;
2409 };
2410
2411 MULTI_THREAD_TEST_F(LayerTreeHostScrollTestImplSideInvalidation);
2412
2413 class NonScrollingNonFastScrollableRegion : public LayerTreeHostScrollTest {
2414 public:
NonScrollingNonFastScrollableRegion()2415 NonScrollingNonFastScrollableRegion() { SetUseLayerLists(); }
2416
2417 // Setup 3 Layers:
2418 // 1) bottom_ which has a non-fast region in the bottom-right.
2419 // 2) middle_scrollable_ which is scrollable.
2420 // 3) top_ which has a non-fast region in the top-left and is offset by
2421 // |middle_scrollable_|'s scroll offset.
SetupTree()2422 void SetupTree() override {
2423 SetInitialRootBounds(gfx::Size(800, 600));
2424 LayerTreeHostScrollTest::SetupTree();
2425 Layer* root = layer_tree_host()->root_layer();
2426 fake_content_layer_client_.set_bounds(root->bounds());
2427
2428 bottom_ = FakePictureLayer::Create(&fake_content_layer_client_);
2429 bottom_->SetElementId(LayerIdToElementIdForTesting(bottom_->id()));
2430 bottom_->SetBounds(gfx::Size(100, 100));
2431 bottom_->SetNonFastScrollableRegion(Region(gfx::Rect(50, 50, 50, 50)));
2432 bottom_->SetHitTestable(true);
2433 CopyProperties(root, bottom_.get());
2434 root->AddChild(bottom_);
2435
2436 middle_scrollable_ = FakePictureLayer::Create(&fake_content_layer_client_);
2437 middle_scrollable_->SetElementId(
2438 LayerIdToElementIdForTesting(middle_scrollable_->id()));
2439 middle_scrollable_->SetBounds(gfx::Size(100, 100));
2440 middle_scrollable_->SetIsDrawable(true);
2441 middle_scrollable_->SetHitTestable(true);
2442 CopyProperties(bottom_.get(), middle_scrollable_.get());
2443 CreateTransformNode(middle_scrollable_.get());
2444 CreateScrollNode(middle_scrollable_.get(), gfx::Size(100, 200));
2445 root->AddChild(middle_scrollable_);
2446
2447 top_ = FakePictureLayer::Create(&fake_content_layer_client_);
2448 top_->SetElementId(LayerIdToElementIdForTesting(top_->id()));
2449 top_->SetBounds(gfx::Size(100, 100));
2450 top_->SetNonFastScrollableRegion(Region(gfx::Rect(0, 0, 50, 50)));
2451 top_->SetHitTestable(true);
2452 CopyProperties(middle_scrollable_.get(), top_.get());
2453 root->AddChild(top_);
2454 }
2455
BeginTest()2456 void BeginTest() override { PostSetNeedsCommitToMainThread(); }
2457
CommitCompleteOnThread(LayerTreeHostImpl * impl)2458 void CommitCompleteOnThread(LayerTreeHostImpl* impl) override {
2459 if (TestEnded())
2460 return;
2461
2462 // The top-left hit should immediately hit the top layer's non-fast region
2463 // which forces main-thread scrolling.
2464 auto top_left_status = impl->ScrollBegin(
2465 BeginState(gfx::Point(20, 20)).get(), ScrollInputType::kTouchscreen);
2466 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, top_left_status.thread);
2467 EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
2468 top_left_status.main_thread_scrolling_reasons);
2469
2470 // The top-right hit should hit the top layer but not the non-fast region so
2471 // the scroll should continue to scroll on the impl.
2472 InputHandler::ScrollStatus top_right_status = impl->ScrollBegin(
2473 BeginState(gfx::Point(80, 20)).get(), ScrollInputType::kTouchscreen);
2474 EXPECT_EQ(InputHandler::SCROLL_ON_IMPL_THREAD, top_right_status.thread);
2475 EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain,
2476 top_right_status.main_thread_scrolling_reasons);
2477 impl->ScrollEnd();
2478
2479 // The bottom-right should hit the bottom layer's non-fast region. Though
2480 // the middle layer is a composited scroller and is hit first, we cannot do
2481 // a fast scroll because an ancestor on the scroll chain has hit a non-fast
2482 // region.
2483 InputHandler::ScrollStatus bottom_right_status = impl->ScrollBegin(
2484 BeginState(gfx::Point(80, 80)).get(), ScrollInputType::kTouchscreen);
2485 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD, bottom_right_status.thread);
2486 EXPECT_EQ(MainThreadScrollingReason::kNonFastScrollableRegion,
2487 bottom_right_status.main_thread_scrolling_reasons);
2488
2489 EndTest();
2490 }
2491
2492 private:
2493 FakeContentLayerClient fake_content_layer_client_;
2494 scoped_refptr<Layer> bottom_;
2495 scoped_refptr<Layer> middle_scrollable_;
2496 scoped_refptr<Layer> top_;
2497 };
2498
2499 SINGLE_THREAD_TEST_F(NonScrollingNonFastScrollableRegion);
2500
2501 } // namespace
2502 } // namespace cc
2503