ipc: Convert k(u)int*max types from basictypes.h to std::numeric_limits variants.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blobf5a414b8d7e4eaf3c0ba61ed178ee21e3756d6ef
1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
7 #include <algorithm>
8 #include <cmath>
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "base/location.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "cc/animation/scrollbar_animation_controller_thinning.h"
17 #include "cc/animation/transform_operations.h"
18 #include "cc/base/math_util.h"
19 #include "cc/input/page_scale_animation.h"
20 #include "cc/input/top_controls_manager.h"
21 #include "cc/layers/append_quads_data.h"
22 #include "cc/layers/delegated_renderer_layer_impl.h"
23 #include "cc/layers/heads_up_display_layer_impl.h"
24 #include "cc/layers/io_surface_layer_impl.h"
25 #include "cc/layers/layer_impl.h"
26 #include "cc/layers/painted_scrollbar_layer_impl.h"
27 #include "cc/layers/render_surface_impl.h"
28 #include "cc/layers/solid_color_layer_impl.h"
29 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
30 #include "cc/layers/texture_layer_impl.h"
31 #include "cc/layers/video_layer_impl.h"
32 #include "cc/layers/viewport.h"
33 #include "cc/output/begin_frame_args.h"
34 #include "cc/output/compositor_frame_ack.h"
35 #include "cc/output/compositor_frame_metadata.h"
36 #include "cc/output/copy_output_request.h"
37 #include "cc/output/copy_output_result.h"
38 #include "cc/output/gl_renderer.h"
39 #include "cc/output/latency_info_swap_promise.h"
40 #include "cc/quads/render_pass_draw_quad.h"
41 #include "cc/quads/solid_color_draw_quad.h"
42 #include "cc/quads/texture_draw_quad.h"
43 #include "cc/quads/tile_draw_quad.h"
44 #include "cc/test/animation_test_common.h"
45 #include "cc/test/begin_frame_args_test.h"
46 #include "cc/test/fake_layer_tree_host_impl.h"
47 #include "cc/test/fake_output_surface.h"
48 #include "cc/test/fake_output_surface_client.h"
49 #include "cc/test/fake_picture_layer_impl.h"
50 #include "cc/test/fake_picture_pile_impl.h"
51 #include "cc/test/fake_proxy.h"
52 #include "cc/test/fake_video_frame_provider.h"
53 #include "cc/test/geometry_test_utils.h"
54 #include "cc/test/gpu_rasterization_enabled_settings.h"
55 #include "cc/test/layer_test_common.h"
56 #include "cc/test/layer_tree_test.h"
57 #include "cc/test/test_gpu_memory_buffer_manager.h"
58 #include "cc/test/test_shared_bitmap_manager.h"
59 #include "cc/test/test_task_graph_runner.h"
60 #include "cc/test/test_web_graphics_context_3d.h"
61 #include "cc/trees/layer_tree_impl.h"
62 #include "cc/trees/single_thread_proxy.h"
63 #include "media/base/media.h"
64 #include "testing/gmock/include/gmock/gmock.h"
65 #include "testing/gtest/include/gtest/gtest.h"
66 #include "third_party/skia/include/core/SkMallocPixelRef.h"
67 #include "ui/gfx/geometry/rect_conversions.h"
68 #include "ui/gfx/geometry/size_conversions.h"
69 #include "ui/gfx/geometry/vector2d_conversions.h"
71 using ::testing::Mock;
72 using ::testing::Return;
73 using ::testing::AnyNumber;
74 using ::testing::AtLeast;
75 using ::testing::_;
76 using media::VideoFrame;
78 namespace cc {
79 namespace {
81 class LayerTreeHostImplTest : public testing::Test,
82 public LayerTreeHostImplClient {
83 public:
84 LayerTreeHostImplTest()
85 : proxy_(base::ThreadTaskRunnerHandle::Get(),
86 base::ThreadTaskRunnerHandle::Get()),
87 always_impl_thread_(&proxy_),
88 always_main_thread_blocked_(&proxy_),
89 on_can_draw_state_changed_called_(false),
90 did_notify_ready_to_activate_(false),
91 did_request_commit_(false),
92 did_request_redraw_(false),
93 did_request_animate_(false),
94 did_request_prepare_tiles_(false),
95 did_complete_page_scale_animation_(false),
96 reduce_memory_result_(true) {
97 media::InitializeMediaLibrary();
100 LayerTreeSettings DefaultSettings() {
101 LayerTreeSettings settings;
102 settings.minimum_occlusion_tracking_size = gfx::Size();
103 settings.renderer_settings.texture_id_allocation_chunk_size = 1;
104 settings.gpu_rasterization_enabled = true;
105 return settings;
108 void SetUp() override {
109 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
112 void TearDown() override {}
114 void UpdateRendererCapabilitiesOnImplThread() override {}
115 void DidLoseOutputSurfaceOnImplThread() override {}
116 void CommitVSyncParameters(base::TimeTicks timebase,
117 base::TimeDelta interval) override {}
118 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
119 void SetMaxSwapsPendingOnImplThread(int max) override {}
120 void DidSwapBuffersOnImplThread() override {}
121 void DidSwapBuffersCompleteOnImplThread() override {}
122 void OnCanDrawStateChanged(bool can_draw) override {
123 on_can_draw_state_changed_called_ = true;
125 void NotifyReadyToActivate() override {
126 did_notify_ready_to_activate_ = true;
127 host_impl_->ActivateSyncTree();
129 void NotifyReadyToDraw() override {}
130 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
131 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
132 did_request_redraw_ = true;
134 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
135 void SetNeedsPrepareTilesOnImplThread() override {
136 did_request_prepare_tiles_ = true;
138 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
139 void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
140 void PostAnimationEventsToMainThreadOnImplThread(
141 scoped_ptr<AnimationEventsVector> events) override {}
142 bool IsInsideDraw() override { return false; }
143 void RenewTreePriority() override {}
144 void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
145 base::TimeDelta delay) override {
146 animation_task_ = task;
147 requested_animation_delay_ = delay;
149 void DidActivateSyncTree() override {}
150 void WillPrepareTiles() override {}
151 void DidPrepareTiles() override {}
152 void DidCompletePageScaleAnimationOnImplThread() override {
153 did_complete_page_scale_animation_ = true;
155 void OnDrawForOutputSurface() override {}
156 void PostFrameTimingEventsOnImplThread(
157 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
158 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
159 override {}
161 void set_reduce_memory_result(bool reduce_memory_result) {
162 reduce_memory_result_ = reduce_memory_result;
165 virtual bool CreateHostImpl(const LayerTreeSettings& settings,
166 scoped_ptr<OutputSurface> output_surface) {
167 host_impl_ = LayerTreeHostImpl::Create(
168 settings, this, &proxy_, &stats_instrumentation_,
169 &shared_bitmap_manager_, &gpu_memory_buffer_manager_,
170 &task_graph_runner_, 0);
171 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
172 host_impl_->SetViewportSize(gfx::Size(10, 10));
173 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
174 // Set the BeginFrameArgs so that methods which use it are able to.
175 host_impl_->WillBeginImplFrame(CreateBeginFrameArgsForTesting(
176 BEGINFRAME_FROM_HERE,
177 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1)));
178 host_impl_->DidFinishImplFrame();
179 return init;
182 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
183 root->SetPosition(gfx::PointF());
184 root->SetBounds(gfx::Size(10, 10));
185 root->SetDrawsContent(true);
186 root->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10);
187 root->SetHasRenderSurface(true);
188 host_impl_->active_tree()->SetRootLayer(root.Pass());
191 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
192 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
193 for (size_t i = 0; i < layer->children().size(); ++i)
194 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
197 static ::testing::AssertionResult ScrollInfoContains(
198 const ScrollAndScaleSet& scroll_info,
199 int id,
200 const gfx::Vector2d& scroll_delta) {
201 int times_encountered = 0;
203 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
204 if (scroll_info.scrolls[i].layer_id != id)
205 continue;
207 if (scroll_delta != scroll_info.scrolls[i].scroll_delta) {
208 return ::testing::AssertionFailure()
209 << "Expected " << scroll_delta.ToString() << ", not "
210 << scroll_info.scrolls[i].scroll_delta.ToString();
212 times_encountered++;
215 if (times_encountered != 1)
216 return ::testing::AssertionFailure() << "No layer found with id " << id;
217 return ::testing::AssertionSuccess();
220 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
221 int times_encountered = 0;
223 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
224 if (scroll_info.scrolls[i].layer_id != id)
225 continue;
226 times_encountered++;
229 ASSERT_EQ(0, times_encountered);
232 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
233 const gfx::Size& content_size) {
234 // Create both an inner viewport scroll layer and an outer viewport scroll
235 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
236 // 0x0, so the scrolls will be applied directly to the inner viewport.
237 const int kOuterViewportClipLayerId = 116;
238 const int kOuterViewportScrollLayerId = 117;
239 const int kContentLayerId = 118;
240 const int kInnerViewportScrollLayerId = 2;
241 const int kInnerViewportClipLayerId = 4;
242 const int kPageScaleLayerId = 5;
244 scoped_ptr<LayerImpl> root =
245 LayerImpl::Create(layer_tree_impl, 1);
246 root->SetBounds(content_size);
247 root->SetPosition(gfx::PointF());
248 root->SetHasRenderSurface(true);
250 scoped_ptr<LayerImpl> inner_scroll =
251 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
252 inner_scroll->SetIsContainerForFixedPositionLayers(true);
253 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
255 scoped_ptr<LayerImpl> inner_clip =
256 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
257 inner_clip->SetBounds(
258 gfx::Size(content_size.width() / 2, content_size.height() / 2));
260 scoped_ptr<LayerImpl> page_scale =
261 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
263 inner_scroll->SetScrollClipLayer(inner_clip->id());
264 inner_scroll->SetBounds(content_size);
265 inner_scroll->SetPosition(gfx::PointF());
267 scoped_ptr<LayerImpl> outer_clip =
268 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
269 outer_clip->SetBounds(content_size);
270 outer_clip->SetIsContainerForFixedPositionLayers(true);
272 scoped_ptr<LayerImpl> outer_scroll =
273 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
274 outer_scroll->SetScrollClipLayer(outer_clip->id());
275 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
276 outer_scroll->SetBounds(content_size);
277 outer_scroll->SetPosition(gfx::PointF());
279 scoped_ptr<LayerImpl> contents =
280 LayerImpl::Create(layer_tree_impl, kContentLayerId);
281 contents->SetDrawsContent(true);
282 contents->SetBounds(content_size);
283 contents->SetPosition(gfx::PointF());
285 outer_scroll->AddChild(contents.Pass());
286 outer_clip->AddChild(outer_scroll.Pass());
287 inner_scroll->AddChild(outer_clip.Pass());
288 page_scale->AddChild(inner_scroll.Pass());
289 inner_clip->AddChild(page_scale.Pass());
290 root->AddChild(inner_clip.Pass());
292 layer_tree_impl->SetRootLayer(root.Pass());
293 layer_tree_impl->SetViewportLayersFromIds(
294 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
295 kOuterViewportScrollLayerId);
297 layer_tree_impl->DidBecomeActive();
298 return layer_tree_impl->InnerViewportScrollLayer();
301 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
302 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
303 host_impl_->active_tree(), content_size);
304 host_impl_->active_tree()->DidBecomeActive();
305 return scroll_layer;
308 // Sets up a typical virtual viewport setup with one child content layer.
309 // Returns a pointer to the content layer.
310 LayerImpl* CreateBasicVirtualViewportLayers(const gfx::Size& viewport_size,
311 const gfx::Size& content_size) {
312 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
313 // the inner a different size from the outer. We'll reuse its layer
314 // hierarchy but adjust the sizing to our needs.
315 CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size);
317 LayerImpl* content_layer =
318 host_impl_->OuterViewportScrollLayer()->children().back();
319 content_layer->SetBounds(content_size);
320 host_impl_->OuterViewportScrollLayer()->SetBounds(content_size);
322 LayerImpl* outer_clip = host_impl_->OuterViewportScrollLayer()->parent();
323 outer_clip->SetBounds(viewport_size);
325 LayerImpl* inner_clip_layer =
326 host_impl_->InnerViewportScrollLayer()->parent()->parent();
327 inner_clip_layer->SetBounds(viewport_size);
328 host_impl_->InnerViewportScrollLayer()->SetBounds(viewport_size);
330 host_impl_->SetViewportSize(viewport_size);
331 host_impl_->active_tree()->DidBecomeActive();
333 return content_layer;
336 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
337 const gfx::Size& size,
338 LayerImpl* clip_layer) {
339 DCHECK(clip_layer);
340 DCHECK(id != clip_layer->id());
341 scoped_ptr<LayerImpl> layer =
342 LayerImpl::Create(host_impl_->active_tree(), id);
343 layer->SetScrollClipLayer(clip_layer->id());
344 layer->SetDrawsContent(true);
345 layer->SetBounds(size);
346 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
347 return layer.Pass();
350 void DrawFrame() {
351 LayerTreeHostImpl::FrameData frame;
352 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
353 host_impl_->DrawLayers(&frame);
354 host_impl_->DidDrawAllLayers(frame);
357 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
358 void pinch_zoom_pan_viewport_test(float device_scale_factor);
359 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
360 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
361 float device_scale_factor);
363 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
364 // Note: It is not possible to disable the renderer once it has been set,
365 // so we do not need to test that disabling the renderer notifies us
366 // that can_draw changed.
367 EXPECT_FALSE(host_impl_->CanDraw());
368 on_can_draw_state_changed_called_ = false;
370 // Set up the root layer, which allows us to draw.
371 SetupScrollAndContentsLayers(gfx::Size(100, 100));
372 EXPECT_TRUE(host_impl_->CanDraw());
373 EXPECT_TRUE(on_can_draw_state_changed_called_);
374 on_can_draw_state_changed_called_ = false;
376 // Toggle the root layer to make sure it toggles can_draw
377 host_impl_->active_tree()->SetRootLayer(nullptr);
378 EXPECT_FALSE(host_impl_->CanDraw());
379 EXPECT_TRUE(on_can_draw_state_changed_called_);
380 on_can_draw_state_changed_called_ = false;
382 SetupScrollAndContentsLayers(gfx::Size(100, 100));
383 EXPECT_TRUE(host_impl_->CanDraw());
384 EXPECT_TRUE(on_can_draw_state_changed_called_);
385 on_can_draw_state_changed_called_ = false;
387 // Toggle the device viewport size to make sure it toggles can_draw.
388 host_impl_->SetViewportSize(gfx::Size());
389 if (always_draw) {
390 EXPECT_TRUE(host_impl_->CanDraw());
391 } else {
392 EXPECT_FALSE(host_impl_->CanDraw());
394 EXPECT_TRUE(on_can_draw_state_changed_called_);
395 on_can_draw_state_changed_called_ = false;
397 host_impl_->SetViewportSize(gfx::Size(100, 100));
398 EXPECT_TRUE(host_impl_->CanDraw());
399 EXPECT_TRUE(on_can_draw_state_changed_called_);
400 on_can_draw_state_changed_called_ = false;
403 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
405 protected:
406 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
407 return FakeOutputSurface::Create3d();
410 void DrawOneFrame() {
411 LayerTreeHostImpl::FrameData frame_data;
412 host_impl_->PrepareToDraw(&frame_data);
413 host_impl_->DidDrawAllLayers(frame_data);
416 FakeProxy proxy_;
417 DebugScopedSetImplThread always_impl_thread_;
418 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
420 TestSharedBitmapManager shared_bitmap_manager_;
421 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
422 TestTaskGraphRunner task_graph_runner_;
423 scoped_ptr<LayerTreeHostImpl> host_impl_;
424 FakeRenderingStatsInstrumentation stats_instrumentation_;
425 bool on_can_draw_state_changed_called_;
426 bool did_notify_ready_to_activate_;
427 bool did_request_commit_;
428 bool did_request_redraw_;
429 bool did_request_animate_;
430 bool did_request_prepare_tiles_;
431 bool did_complete_page_scale_animation_;
432 bool reduce_memory_result_;
433 base::Closure animation_task_;
434 base::TimeDelta requested_animation_delay_;
437 // A test fixture for new animation timelines tests.
438 class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest {
439 public:
440 void SetUp() override {
441 LayerTreeSettings settings = DefaultSettings();
442 settings.use_compositor_animation_timelines = true;
443 CreateHostImpl(settings, CreateOutputSurface());
447 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
448 bool always_draw = false;
449 CheckNotifyCalledIfCanDrawChanged(always_draw);
452 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
453 CreateHostImpl(DefaultSettings(),
454 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
456 bool always_draw = true;
457 CheckNotifyCalledIfCanDrawChanged(always_draw);
460 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
461 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
463 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
464 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
467 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
469 scoped_ptr<LayerImpl> root =
470 LayerImpl::Create(host_impl_->active_tree(), 1);
471 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
472 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
473 root->children()[1]->AddChild(
474 LayerImpl::Create(host_impl_->active_tree(), 4));
475 root->children()[1]->AddChild(
476 LayerImpl::Create(host_impl_->active_tree(), 5));
477 root->children()[1]->children()[0]->AddChild(
478 LayerImpl::Create(host_impl_->active_tree(), 6));
479 host_impl_->active_tree()->SetRootLayer(root.Pass());
481 LayerImpl* root = host_impl_->active_tree()->root_layer();
483 ExpectClearedScrollDeltasRecursive(root);
485 scoped_ptr<ScrollAndScaleSet> scroll_info;
487 scroll_info = host_impl_->ProcessScrollDeltas();
488 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
489 ExpectClearedScrollDeltasRecursive(root);
491 scroll_info = host_impl_->ProcessScrollDeltas();
492 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
493 ExpectClearedScrollDeltasRecursive(root);
496 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
497 gfx::ScrollOffset scroll_offset(20, 30);
498 gfx::Vector2d scroll_delta(11, -15);
500 scoped_ptr<LayerImpl> root_clip =
501 LayerImpl::Create(host_impl_->active_tree(), 2);
502 scoped_ptr<LayerImpl> root =
503 LayerImpl::Create(host_impl_->active_tree(), 1);
504 root_clip->SetBounds(gfx::Size(10, 10));
505 LayerImpl* root_layer = root.get();
506 root_clip->AddChild(root.Pass());
507 root_layer->SetBounds(gfx::Size(110, 110));
508 root_layer->SetScrollClipLayer(root_clip->id());
509 root_layer->PushScrollOffsetFromMainThread(scroll_offset);
510 root_layer->ScrollBy(scroll_delta);
511 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
513 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
515 scoped_ptr<ScrollAndScaleSet> scroll_info;
517 scroll_info = host_impl_->ProcessScrollDeltas();
518 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
519 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(), scroll_delta));
521 gfx::Vector2d scroll_delta2(-5, 27);
522 root->ScrollBy(scroll_delta2);
523 scroll_info = host_impl_->ProcessScrollDeltas();
524 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
525 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(),
526 scroll_delta + scroll_delta2));
528 root->ScrollBy(gfx::Vector2d());
529 scroll_info = host_impl_->ProcessScrollDeltas();
530 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(),
531 scroll_delta + scroll_delta2));
534 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
535 SetupScrollAndContentsLayers(gfx::Size(100, 100));
536 host_impl_->SetViewportSize(gfx::Size(50, 50));
537 DrawFrame();
539 EXPECT_EQ(InputHandler::SCROLL_STARTED,
540 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
541 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
542 InputHandler::WHEEL));
543 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
544 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
545 InputHandler::WHEEL));
546 host_impl_->ScrollEnd();
547 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
548 InputHandler::WHEEL));
549 EXPECT_TRUE(did_request_redraw_);
550 EXPECT_TRUE(did_request_commit_);
553 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
554 SetupScrollAndContentsLayers(gfx::Size(100, 100));
555 host_impl_->SetViewportSize(gfx::Size(50, 50));
556 DrawFrame();
558 EXPECT_EQ(InputHandler::SCROLL_STARTED,
559 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
560 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
561 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
562 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
563 host_impl_->ScrollEnd();
564 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
567 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
568 // We should not crash when trying to scroll an empty layer tree.
569 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
570 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
573 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
574 scoped_ptr<TestWebGraphicsContext3D> context_owned =
575 TestWebGraphicsContext3D::Create();
576 context_owned->set_context_lost(true);
578 // Initialization will fail.
579 EXPECT_FALSE(CreateHostImpl(
580 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
582 SetupScrollAndContentsLayers(gfx::Size(100, 100));
584 // We should not crash when trying to scroll after the renderer initialization
585 // fails.
586 EXPECT_EQ(InputHandler::SCROLL_STARTED,
587 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
590 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
591 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
592 host_impl_->SetViewportSize(gfx::Size(50, 50));
593 DrawFrame();
595 // We should not crash if the tree is replaced while we are scrolling.
596 EXPECT_EQ(InputHandler::SCROLL_STARTED,
597 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
598 host_impl_->active_tree()->DetachLayerTree();
600 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
602 // We should still be scrolling, because the scrolled layer also exists in the
603 // new tree.
604 gfx::Vector2d scroll_delta(0, 10);
605 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
606 host_impl_->ScrollEnd();
607 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
608 EXPECT_TRUE(
609 ScrollInfoContains(*scroll_info, scroll_layer->id(), scroll_delta));
612 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
613 SetupScrollAndContentsLayers(gfx::Size(100, 100));
614 host_impl_->SetViewportSize(gfx::Size(50, 50));
615 DrawFrame();
616 LayerImpl* root = host_impl_->active_tree()->root_layer();
618 // With registered event handlers, wheel scrolls don't necessarily
619 // have to go to the main thread.
620 root->SetHaveWheelEventHandlers(true);
621 EXPECT_EQ(InputHandler::SCROLL_STARTED,
622 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
623 host_impl_->ScrollEnd();
625 // But typically the scroll-blocks-on mode will require them to.
626 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
627 SCROLL_BLOCKS_ON_START_TOUCH);
628 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
629 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
631 // But gesture scrolls can still be handled.
632 EXPECT_EQ(InputHandler::SCROLL_STARTED,
633 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
634 host_impl_->ScrollEnd();
636 // And if the handlers go away, wheel scrolls can again be processed
637 // on impl (despite the scroll-blocks-on mode).
638 root->SetHaveWheelEventHandlers(false);
639 EXPECT_EQ(InputHandler::SCROLL_STARTED,
640 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
641 host_impl_->ScrollEnd();
644 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
645 LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
646 host_impl_->SetViewportSize(gfx::Size(50, 50));
647 DrawFrame();
648 LayerImpl* root = host_impl_->active_tree()->root_layer();
650 LayerImpl* child = 0;
652 scoped_ptr<LayerImpl> child_layer =
653 LayerImpl::Create(host_impl_->active_tree(), 6);
654 child = child_layer.get();
655 child_layer->SetDrawsContent(true);
656 child_layer->SetPosition(gfx::PointF(0, 20));
657 child_layer->SetBounds(gfx::Size(50, 50));
658 scroll->AddChild(child_layer.Pass());
661 // Touch handler regions determine whether touch events block scroll.
662 root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
663 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
664 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH |
665 SCROLL_BLOCKS_ON_WHEEL_EVENT);
666 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
668 // But they don't influence the actual handling of the scroll gestures.
669 EXPECT_EQ(InputHandler::SCROLL_STARTED,
670 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
671 host_impl_->ScrollEnd();
673 // It's the union of scroll-blocks-on mode bits across all layers in the
674 // scroll paret chain that matters.
675 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
676 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE);
677 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
678 child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH);
679 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
682 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
683 SetupScrollAndContentsLayers(gfx::Size(100, 100));
684 host_impl_->SetViewportSize(gfx::Size(50, 50));
685 DrawFrame();
686 LayerImpl* root = host_impl_->active_tree()->root_layer();
688 // With registered scroll handlers, scrolls don't generally have to go
689 // to the main thread.
690 root->SetHaveScrollEventHandlers(true);
691 EXPECT_EQ(InputHandler::SCROLL_STARTED,
692 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
693 host_impl_->ScrollEnd();
695 // Even the default scroll blocks on mode doesn't require this.
696 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
697 SCROLL_BLOCKS_ON_START_TOUCH);
698 EXPECT_EQ(InputHandler::SCROLL_STARTED,
699 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
700 host_impl_->ScrollEnd();
702 // But the page can opt in to blocking on scroll event handlers.
703 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
704 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
705 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
707 // GESTURE and WHEEL scrolls behave identically in this regard.
708 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
709 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
711 // And if the handlers go away, scrolls can again be processed on impl
712 // (despite the scroll-blocks-on mode).
713 root->SetHaveScrollEventHandlers(false);
714 EXPECT_EQ(InputHandler::SCROLL_STARTED,
715 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
716 host_impl_->ScrollEnd();
719 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
720 host_impl_->SetViewportSize(gfx::Size(50, 50));
722 // Create a normal scrollable root layer
723 LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
724 LayerImpl* root_child = root_scroll->children()[0];
725 LayerImpl* root = host_impl_->active_tree()->root_layer();
726 DrawFrame();
728 // Create two child scrollable layers
729 LayerImpl* child1 = 0;
731 scoped_ptr<LayerImpl> scrollable_child_clip_1 =
732 LayerImpl::Create(host_impl_->active_tree(), 6);
733 scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
734 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
735 child1 = scrollable_child_1.get();
736 scrollable_child_1->SetPosition(gfx::Point(5, 5));
737 scrollable_child_1->SetHaveWheelEventHandlers(true);
738 scrollable_child_1->SetHaveScrollEventHandlers(true);
739 scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
740 root_child->AddChild(scrollable_child_clip_1.Pass());
743 LayerImpl* child2 = 0;
745 scoped_ptr<LayerImpl> scrollable_child_clip_2 =
746 LayerImpl::Create(host_impl_->active_tree(), 8);
747 scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
748 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
749 child2 = scrollable_child_2.get();
750 scrollable_child_2->SetPosition(gfx::Point(5, 20));
751 scrollable_child_2->SetHaveWheelEventHandlers(true);
752 scrollable_child_2->SetHaveScrollEventHandlers(true);
753 scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
754 root_child->AddChild(scrollable_child_clip_2.Pass());
757 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
758 EXPECT_EQ(InputHandler::SCROLL_STARTED,
759 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
760 host_impl_->ScrollEnd();
761 child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
762 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
763 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
765 // But not those that hit only other layers.
766 EXPECT_EQ(InputHandler::SCROLL_STARTED,
767 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
768 host_impl_->ScrollEnd();
770 // It's the union of bits set across the scroll ancestor chain that matters.
771 EXPECT_EQ(InputHandler::SCROLL_STARTED,
772 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
773 host_impl_->ScrollEnd();
774 EXPECT_EQ(InputHandler::SCROLL_STARTED,
775 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
776 host_impl_->ScrollEnd();
777 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT);
778 EXPECT_EQ(InputHandler::SCROLL_STARTED,
779 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
780 host_impl_->ScrollEnd();
781 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
782 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
783 child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
784 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
785 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
786 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
787 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
790 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
791 SetupScrollAndContentsLayers(gfx::Size(100, 100));
792 host_impl_->SetViewportSize(gfx::Size(50, 50));
793 DrawFrame();
795 // Ignore the fling since no layer is being scrolled
796 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
798 // Start scrolling a layer
799 EXPECT_EQ(InputHandler::SCROLL_STARTED,
800 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
802 // Now the fling should go ahead since we've started scrolling a layer
803 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
806 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
807 SetupScrollAndContentsLayers(gfx::Size(100, 100));
808 host_impl_->SetViewportSize(gfx::Size(50, 50));
809 DrawFrame();
811 // Ignore the fling since no layer is being scrolled
812 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
814 // Start scrolling a layer
815 EXPECT_EQ(InputHandler::SCROLL_STARTED,
816 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
818 // Now the fling should go ahead since we've started scrolling a layer
819 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
822 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
823 SetupScrollAndContentsLayers(gfx::Size(100, 100));
824 host_impl_->SetViewportSize(gfx::Size(50, 50));
825 DrawFrame();
826 LayerImpl* root = host_impl_->active_tree()->root_layer();
828 root->SetShouldScrollOnMainThread(true);
830 // Start scrolling a layer
831 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
832 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
834 // The fling should be ignored since there's no layer being scrolled impl-side
835 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
838 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
839 SetupScrollAndContentsLayers(gfx::Size(100, 100));
840 host_impl_->SetViewportSize(gfx::Size(50, 50));
841 DrawFrame();
842 LayerImpl* root = host_impl_->active_tree()->root_layer();
844 root->SetShouldScrollOnMainThread(true);
846 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
847 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
848 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
849 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
852 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
853 SetupScrollAndContentsLayers(gfx::Size(200, 200));
854 host_impl_->SetViewportSize(gfx::Size(100, 100));
856 LayerImpl* root = host_impl_->active_tree()->root_layer();
857 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
859 DrawFrame();
861 // All scroll types inside the non-fast scrollable region should fail.
862 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
863 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL));
864 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
865 InputHandler::WHEEL));
866 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
867 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE));
868 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
869 InputHandler::GESTURE));
871 // All scroll types outside this region should succeed.
872 EXPECT_EQ(InputHandler::SCROLL_STARTED,
873 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL));
874 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
875 InputHandler::GESTURE));
876 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
877 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
878 InputHandler::GESTURE));
879 host_impl_->ScrollEnd();
880 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
881 InputHandler::GESTURE));
882 EXPECT_EQ(InputHandler::SCROLL_STARTED,
883 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE));
884 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
885 InputHandler::GESTURE));
886 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
887 host_impl_->ScrollEnd();
888 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
889 InputHandler::GESTURE));
892 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
893 SetupScrollAndContentsLayers(gfx::Size(200, 200));
894 host_impl_->SetViewportSize(gfx::Size(100, 100));
896 LayerImpl* root = host_impl_->active_tree()->root_layer();
897 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
898 root->SetPosition(gfx::PointF(-25.f, 0.f));
900 DrawFrame();
902 // This point would fall into the non-fast scrollable region except that we've
903 // moved the layer down by 25 pixels.
904 EXPECT_EQ(InputHandler::SCROLL_STARTED,
905 host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL));
906 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
907 InputHandler::WHEEL));
908 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
909 host_impl_->ScrollEnd();
911 // This point is still inside the non-fast region.
912 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
913 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL));
916 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
917 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
918 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
919 host_impl_->SetViewportSize(gfx::Size(50, 50));
920 DrawFrame();
922 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
923 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
924 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
925 host_impl_->ScrollEnd();
926 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
929 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
930 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
931 scroll_layer->SetHaveScrollEventHandlers(true);
932 host_impl_->SetViewportSize(gfx::Size(50, 50));
933 DrawFrame();
935 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
936 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
937 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
938 host_impl_->ScrollEnd();
939 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
942 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
943 SetupScrollAndContentsLayers(gfx::Size(200, 200));
944 host_impl_->SetViewportSize(gfx::Size(100, 100));
946 DrawFrame();
948 EXPECT_EQ(InputHandler::SCROLL_STARTED,
949 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
951 // Trying to scroll to the left/top will not succeed.
952 EXPECT_FALSE(
953 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
954 EXPECT_FALSE(
955 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
956 EXPECT_FALSE(
957 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
959 // Scrolling to the right/bottom will succeed.
960 EXPECT_TRUE(
961 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
962 EXPECT_TRUE(
963 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
964 EXPECT_TRUE(
965 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
967 // Scrolling to left/top will now succeed.
968 EXPECT_TRUE(
969 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
970 EXPECT_TRUE(
971 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
972 EXPECT_TRUE(
973 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
975 // Scrolling diagonally against an edge will succeed.
976 EXPECT_TRUE(
977 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
978 EXPECT_TRUE(
979 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
980 EXPECT_TRUE(
981 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
983 // Trying to scroll more than the available space will also succeed.
984 EXPECT_TRUE(
985 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
988 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
989 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
990 host_impl_->SetViewportSize(gfx::Size(100, 1000));
992 DrawFrame();
994 EXPECT_EQ(InputHandler::SCROLL_STARTED,
995 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
997 // Trying to scroll without a vertical scrollbar will fail.
998 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
999 gfx::Point(), SCROLL_FORWARD));
1000 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
1001 gfx::Point(), SCROLL_BACKWARD));
1003 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
1004 PaintedScrollbarLayerImpl::Create(
1005 host_impl_->active_tree(),
1007 VERTICAL));
1008 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
1009 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
1010 vertical_scrollbar.get());
1012 // Trying to scroll with a vertical scrollbar will succeed.
1013 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1014 gfx::Point(), SCROLL_FORWARD));
1015 EXPECT_FLOAT_EQ(875.f,
1016 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
1017 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1018 gfx::Point(), SCROLL_BACKWARD));
1021 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
1022 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
1023 host_impl_->SetViewportSize(gfx::Size(100, 100));
1025 gfx::Size overflow_size(400, 400);
1026 ASSERT_EQ(1u, scroll_layer->children().size());
1027 LayerImpl* overflow = scroll_layer->children()[0];
1028 overflow->SetBounds(overflow_size);
1029 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
1030 overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1031 overflow->SetPosition(gfx::PointF());
1033 DrawFrame();
1034 gfx::Point scroll_position(10, 10);
1036 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1037 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1038 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1039 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
1041 gfx::Vector2dF scroll_delta(10, 10);
1042 host_impl_->ScrollBy(scroll_position, scroll_delta);
1043 host_impl_->ScrollEnd();
1044 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1045 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1047 overflow->set_user_scrollable_horizontal(false);
1049 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1050 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1052 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1054 host_impl_->ScrollBy(scroll_position, scroll_delta);
1055 host_impl_->ScrollEnd();
1056 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1057 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1059 overflow->set_user_scrollable_vertical(false);
1061 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1062 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1063 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1064 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1066 host_impl_->ScrollBy(scroll_position, scroll_delta);
1067 host_impl_->ScrollEnd();
1068 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
1069 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1072 TEST_F(LayerTreeHostImplTest, AnimationSchedulingPendingTree) {
1073 host_impl_->SetViewportSize(gfx::Size(50, 50));
1075 host_impl_->CreatePendingTree();
1076 host_impl_->pending_tree()->SetRootLayer(
1077 LayerImpl::Create(host_impl_->pending_tree(), 1));
1078 LayerImpl* root = host_impl_->pending_tree()->root_layer();
1079 root->SetBounds(gfx::Size(50, 50));
1080 root->SetHasRenderSurface(true);
1082 root->AddChild(LayerImpl::Create(host_impl_->pending_tree(), 2));
1083 LayerImpl* child = root->children()[0];
1084 child->SetBounds(gfx::Size(10, 10));
1085 child->draw_properties().visible_layer_rect = gfx::Rect(10, 10);
1086 child->SetDrawsContent(true);
1087 AddAnimatedTransformToLayer(child, 10.0, 3, 0);
1089 EXPECT_FALSE(did_request_animate_);
1090 EXPECT_FALSE(did_request_redraw_);
1091 EXPECT_FALSE(did_request_commit_);
1093 host_impl_->Animate();
1095 // An animation exists on the pending layer. Doing Animate() requests another
1096 // frame.
1097 // In reality, animations without has_set_start_time() == true do not need to
1098 // be continuously ticked on the pending tree, so it should not request
1099 // another animation frame here. But we currently do so blindly if any
1100 // animation exists.
1101 EXPECT_TRUE(did_request_animate_);
1102 // The pending tree with an animation does not need to draw after animating.
1103 EXPECT_FALSE(did_request_redraw_);
1104 EXPECT_FALSE(did_request_commit_);
1106 did_request_animate_ = false;
1107 did_request_redraw_ = false;
1108 did_request_commit_ = false;
1110 host_impl_->ActivateSyncTree();
1112 // When the animation activates, we should request another animation frame
1113 // to keep the animation moving.
1114 EXPECT_TRUE(did_request_animate_);
1115 // On activation we don't need to request a redraw for the animation,
1116 // activating will draw on its own when it's ready.
1117 EXPECT_FALSE(did_request_redraw_);
1118 EXPECT_FALSE(did_request_commit_);
1121 TEST_F(LayerTreeHostImplTest, AnimationSchedulingActiveTree) {
1122 host_impl_->SetViewportSize(gfx::Size(50, 50));
1124 host_impl_->active_tree()->SetRootLayer(
1125 LayerImpl::Create(host_impl_->active_tree(), 1));
1126 LayerImpl* root = host_impl_->active_tree()->root_layer();
1127 root->SetBounds(gfx::Size(50, 50));
1128 root->SetHasRenderSurface(true);
1130 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
1131 LayerImpl* child = root->children()[0];
1132 child->SetBounds(gfx::Size(10, 10));
1133 child->draw_properties().visible_layer_rect = gfx::Rect(10, 10);
1134 child->SetDrawsContent(true);
1136 // Add a translate from 6,7 to 8,9.
1137 TransformOperations start;
1138 start.AppendTranslate(6.f, 7.f, 0.f);
1139 TransformOperations end;
1140 end.AppendTranslate(8.f, 9.f, 0.f);
1141 AddAnimatedTransformToLayer(child, 4.0, start, end);
1143 base::TimeTicks now = base::TimeTicks::Now();
1144 host_impl_->WillBeginImplFrame(
1145 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, now));
1147 EXPECT_FALSE(did_request_animate_);
1148 EXPECT_FALSE(did_request_redraw_);
1149 EXPECT_FALSE(did_request_commit_);
1151 host_impl_->ActivateAnimations();
1152 did_request_animate_ = false;
1153 did_request_redraw_ = false;
1154 did_request_commit_ = false;
1156 host_impl_->Animate();
1158 // An animation exists on the active layer. Doing Animate() requests another
1159 // frame after the current one.
1160 EXPECT_TRUE(did_request_animate_);
1161 // TODO(danakj): We also need to draw in the current frame if something
1162 // animated, but this is currently handled by
1163 // SchedulerStateMachine::WillAnimate.
1164 EXPECT_FALSE(did_request_redraw_);
1165 EXPECT_FALSE(did_request_commit_);
1168 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
1169 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
1170 host_impl_->SetViewportSize(gfx::Size(50, 50));
1171 DrawFrame();
1173 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
1174 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
1175 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1177 float min_page_scale = 1.f, max_page_scale = 4.f;
1178 float page_scale_factor = 1.f;
1180 // The impl-based pinch zoom should adjust the max scroll position.
1182 host_impl_->active_tree()->PushPageScaleFromMainThread(
1183 page_scale_factor, min_page_scale, max_page_scale);
1184 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1185 scroll_layer->SetScrollDelta(gfx::Vector2d());
1187 float page_scale_delta = 2.f;
1189 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1190 host_impl_->PinchGestureBegin();
1191 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1192 host_impl_->PinchGestureEnd();
1193 host_impl_->ScrollEnd();
1194 EXPECT_FALSE(did_request_animate_);
1195 EXPECT_TRUE(did_request_redraw_);
1196 EXPECT_TRUE(did_request_commit_);
1197 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1199 scoped_ptr<ScrollAndScaleSet> scroll_info =
1200 host_impl_->ProcessScrollDeltas();
1201 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1203 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1204 scroll_layer->MaxScrollOffset().ToString());
1207 // Scrolling after a pinch gesture should always be in local space. The
1208 // scroll deltas have the page scale factor applied.
1210 host_impl_->active_tree()->PushPageScaleFromMainThread(
1211 page_scale_factor, min_page_scale, max_page_scale);
1212 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1213 scroll_layer->SetScrollDelta(gfx::Vector2d());
1215 float page_scale_delta = 2.f;
1216 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1217 host_impl_->PinchGestureBegin();
1218 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1219 host_impl_->PinchGestureEnd();
1220 host_impl_->ScrollEnd();
1222 gfx::Vector2d scroll_delta(0, 10);
1223 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1224 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
1225 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1226 host_impl_->ScrollEnd();
1228 scoped_ptr<ScrollAndScaleSet> scroll_info =
1229 host_impl_->ProcessScrollDeltas();
1230 EXPECT_TRUE(ScrollInfoContains(
1231 *scroll_info.get(), scroll_layer->id(),
1232 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta)));
1236 TEST_F(LayerTreeHostImplTest, ViewportScrollOrder) {
1237 LayerTreeSettings settings = DefaultSettings();
1238 settings.invert_viewport_scroll_order = true;
1239 CreateHostImpl(settings,
1240 CreateOutputSurface());
1241 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.25f, 4.f);
1243 const gfx::Size content_size(1000, 1000);
1244 const gfx::Size viewport_size(500, 500);
1245 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1247 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1248 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1250 EXPECT_VECTOR_EQ(
1251 gfx::Vector2dF(500, 500),
1252 outer_scroll_layer->MaxScrollOffset());
1254 host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
1255 host_impl_->PinchGestureBegin();
1256 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1257 host_impl_->PinchGestureEnd();
1258 host_impl_->ScrollEnd();
1260 // Sanity check - we're zoomed in, starting from the origin.
1261 EXPECT_VECTOR_EQ(
1262 gfx::Vector2dF(0, 0),
1263 outer_scroll_layer->CurrentScrollOffset());
1264 EXPECT_VECTOR_EQ(
1265 gfx::Vector2dF(0, 0),
1266 inner_scroll_layer->CurrentScrollOffset());
1268 // Scroll down - only the inner viewport should scroll.
1269 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1270 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f));
1271 host_impl_->ScrollEnd();
1273 EXPECT_VECTOR_EQ(
1274 gfx::Vector2dF(50, 50),
1275 inner_scroll_layer->CurrentScrollOffset());
1276 EXPECT_VECTOR_EQ(
1277 gfx::Vector2dF(0, 0),
1278 outer_scroll_layer->CurrentScrollOffset());
1280 // Scroll down - outer viewport should start scrolling after the inner is at
1281 // its maximum.
1282 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1283 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f, 1000.f));
1284 host_impl_->ScrollEnd();
1286 EXPECT_VECTOR_EQ(
1287 gfx::Vector2dF(250, 250),
1288 inner_scroll_layer->CurrentScrollOffset());
1289 EXPECT_VECTOR_EQ(
1290 gfx::Vector2dF(300, 300),
1291 outer_scroll_layer->CurrentScrollOffset());
1294 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1295 // as expected. That is, scrolling during a pinch should bubble from the inner
1296 // to the outer viewport.
1297 TEST_F(LayerTreeHostImplTest, ScrollDuringPinchGesture) {
1298 LayerTreeSettings settings = DefaultSettings();
1299 settings.invert_viewport_scroll_order = true;
1300 CreateHostImpl(settings,
1301 CreateOutputSurface());
1302 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
1304 const gfx::Size content_size(1000, 1000);
1305 const gfx::Size viewport_size(500, 500);
1306 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1308 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1309 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1311 EXPECT_VECTOR_EQ(
1312 gfx::Vector2dF(500, 500),
1313 outer_scroll_layer->MaxScrollOffset());
1315 host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
1316 host_impl_->PinchGestureBegin();
1318 host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
1319 EXPECT_VECTOR_EQ(
1320 gfx::Vector2dF(0, 0),
1321 outer_scroll_layer->CurrentScrollOffset());
1322 EXPECT_VECTOR_EQ(
1323 gfx::Vector2dF(125, 125),
1324 inner_scroll_layer->CurrentScrollOffset());
1326 // Needed so that the pinch is accounted for in draw properties.
1327 DrawFrame();
1329 host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f));
1330 EXPECT_VECTOR_EQ(
1331 gfx::Vector2dF(0, 0),
1332 outer_scroll_layer->CurrentScrollOffset());
1333 EXPECT_VECTOR_EQ(
1334 gfx::Vector2dF(130, 130),
1335 inner_scroll_layer->CurrentScrollOffset());
1337 DrawFrame();
1339 host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f, 400.f));
1340 EXPECT_VECTOR_EQ(
1341 gfx::Vector2dF(80, 80),
1342 outer_scroll_layer->CurrentScrollOffset());
1343 EXPECT_VECTOR_EQ(
1344 gfx::Vector2dF(250, 250),
1345 inner_scroll_layer->CurrentScrollOffset());
1347 host_impl_->PinchGestureEnd();
1348 host_impl_->ScrollEnd();
1351 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1352 // a pinch zoom is anchored within a certain margin of the screen edge, we
1353 // should assume the user means to scroll into the edge of the screen.
1354 TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
1355 LayerTreeSettings settings = DefaultSettings();
1356 settings.invert_viewport_scroll_order = true;
1357 CreateHostImpl(settings,
1358 CreateOutputSurface());
1359 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
1361 const gfx::Size content_size(1000, 1000);
1362 const gfx::Size viewport_size(500, 500);
1363 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1365 int offsetFromEdge = Viewport::kPinchZoomSnapMarginDips - 5;
1366 gfx::Point anchor(viewport_size.width() - offsetFromEdge,
1367 viewport_size.height() - offsetFromEdge);
1369 // Pinch in within the margins. The scroll should stay exactly locked to the
1370 // bottom and right.
1371 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1372 host_impl_->PinchGestureBegin();
1373 host_impl_->PinchGestureUpdate(2, anchor);
1374 host_impl_->PinchGestureEnd();
1375 host_impl_->ScrollEnd();
1377 EXPECT_VECTOR_EQ(
1378 gfx::Vector2dF(250, 250),
1379 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1381 // Reset.
1382 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1383 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1384 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1386 // Pinch in within the margins. The scroll should stay exactly locked to the
1387 // top and left.
1388 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1389 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1390 host_impl_->PinchGestureBegin();
1391 host_impl_->PinchGestureUpdate(2, anchor);
1392 host_impl_->PinchGestureEnd();
1393 host_impl_->ScrollEnd();
1395 EXPECT_VECTOR_EQ(
1396 gfx::Vector2dF(0, 0),
1397 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1399 // Reset.
1400 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1401 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1402 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1404 // Pinch in just outside the margin. There should be no snapping.
1405 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1406 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1407 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1408 host_impl_->PinchGestureBegin();
1409 host_impl_->PinchGestureUpdate(2, anchor);
1410 host_impl_->PinchGestureEnd();
1411 host_impl_->ScrollEnd();
1413 EXPECT_VECTOR_EQ(
1414 gfx::Vector2dF(50, 50),
1415 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1417 // Reset.
1418 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1419 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1420 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1422 // Pinch in just outside the margin. There should be no snapping.
1423 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1424 anchor = gfx::Point(viewport_size.width() - offsetFromEdge,
1425 viewport_size.height() - offsetFromEdge);
1426 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1427 host_impl_->PinchGestureBegin();
1428 host_impl_->PinchGestureUpdate(2, anchor);
1429 host_impl_->PinchGestureEnd();
1430 host_impl_->ScrollEnd();
1432 EXPECT_VECTOR_EQ(
1433 gfx::Vector2dF(200, 200),
1434 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1437 TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
1438 const gfx::Size content_size(200, 200);
1439 const gfx::Size viewport_size(100, 100);
1440 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1442 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1443 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1445 // Zoom into the page by a 2X factor
1446 float min_page_scale = 1.f, max_page_scale = 4.f;
1447 float page_scale_factor = 2.f;
1448 host_impl_->active_tree()->PushPageScaleFromMainThread(
1449 page_scale_factor, min_page_scale, max_page_scale);
1450 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1452 // Scroll by a small amount, there should be no bubbling up to the inner
1453 // viewport.
1454 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1455 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f));
1456 host_impl_->ScrollEnd();
1458 EXPECT_VECTOR_EQ(
1459 gfx::Vector2dF(5, 10),
1460 outer_scroll_layer->CurrentScrollOffset());
1461 EXPECT_VECTOR_EQ(
1462 gfx::Vector2dF(),
1463 inner_scroll_layer->CurrentScrollOffset());
1465 // Scroll by the outer viewport's max scroll extent, there the remainder
1466 // should bubble up to the inner viewport.
1467 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1468 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f));
1469 host_impl_->ScrollEnd();
1471 EXPECT_VECTOR_EQ(
1472 gfx::Vector2dF(100, 100),
1473 outer_scroll_layer->CurrentScrollOffset());
1474 EXPECT_VECTOR_EQ(
1475 gfx::Vector2dF(5, 10),
1476 inner_scroll_layer->CurrentScrollOffset());
1478 // Scroll by the inner viewport's max scroll extent, it should all go to the
1479 // inner viewport.
1480 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1481 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f, 80.f));
1482 host_impl_->ScrollEnd();
1484 EXPECT_VECTOR_EQ(
1485 gfx::Vector2dF(100, 100),
1486 outer_scroll_layer->CurrentScrollOffset());
1487 EXPECT_VECTOR_EQ(
1488 gfx::Vector2dF(50, 50),
1489 inner_scroll_layer->CurrentScrollOffset());
1492 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
1493 ui::LatencyInfo latency_info;
1494 latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
1495 1234);
1496 scoped_ptr<SwapPromise> swap_promise(
1497 new LatencyInfoSwapPromise(latency_info));
1499 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1500 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1501 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
1502 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1503 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
1504 host_impl_->ScrollEnd();
1506 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1507 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1508 EXPECT_EQ(latency_info.trace_id(), scroll_info->swap_promises[0]->TraceId());
1511 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1512 // up to the scroll_parent, rather than the stacking parent.
1513 TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
1514 LayerImpl* viewport_scroll =
1515 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1516 host_impl_->SetViewportSize(gfx::Size(50, 50));
1518 // Set up two scrolling children of the root, one of which is a scroll parent
1519 // to the other. Scrolls bubbling from the child should bubble to the parent,
1520 // not the viewport.
1521 LayerImpl *parent;
1522 LayerImpl *child;
1523 LayerImpl *child_clip;
1525 scoped_ptr<LayerImpl> scroll_parent_clip =
1526 LayerImpl::Create(host_impl_->active_tree(), 6);
1527 scoped_ptr<LayerImpl> scroll_parent = CreateScrollableLayer(
1528 7, gfx::Size(10, 10), scroll_parent_clip.get());
1529 parent = scroll_parent.get();
1530 scroll_parent_clip->AddChild(scroll_parent.Pass());
1532 viewport_scroll->AddChild(scroll_parent_clip.Pass());
1534 scoped_ptr<LayerImpl> scroll_child_clip =
1535 LayerImpl::Create(host_impl_->active_tree(), 8);
1536 scoped_ptr<LayerImpl> scroll_child = CreateScrollableLayer(
1537 9, gfx::Size(10, 10), scroll_child_clip.get());
1538 child = scroll_child.get();
1539 scroll_child->SetPosition(gfx::Point(20, 20));
1540 scroll_child_clip->AddChild(scroll_child.Pass());
1542 child_clip = scroll_child_clip.get();
1543 viewport_scroll->AddChild(scroll_child_clip.Pass());
1545 child_clip->SetScrollParent(parent);
1547 DrawFrame();
1550 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1551 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1552 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1553 host_impl_->ScrollEnd();
1555 // The child should be fully scrolled by the first ScrollBy.
1556 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child->CurrentScrollOffset());
1558 // The scroll_parent should receive the bubbled up second ScrollBy.
1559 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent->CurrentScrollOffset());
1561 // The viewport shouldn't have been scrolled at all.
1562 EXPECT_VECTOR_EQ(
1563 gfx::Vector2dF(0, 0),
1564 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1565 EXPECT_VECTOR_EQ(
1566 gfx::Vector2dF(0, 0),
1567 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1571 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1572 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1573 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1574 host_impl_->ScrollEnd();
1576 // The first ScrollBy should scroll the parent to its extent.
1577 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent->CurrentScrollOffset());
1579 // The viewport should now be next in bubbling order.
1580 EXPECT_VECTOR_EQ(
1581 gfx::Vector2dF(2, 1),
1582 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1583 EXPECT_VECTOR_EQ(
1584 gfx::Vector2dF(0, 0),
1585 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1590 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1591 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1592 host_impl_->SetViewportSize(gfx::Size(50, 50));
1593 DrawFrame();
1595 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1596 DCHECK(scroll_layer);
1598 float min_page_scale = 1.f;
1599 float max_page_scale = 4.f;
1601 // Basic pinch zoom in gesture
1603 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1604 max_page_scale);
1605 scroll_layer->SetScrollDelta(gfx::Vector2d());
1607 float page_scale_delta = 2.f;
1608 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1609 host_impl_->PinchGestureBegin();
1610 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1611 host_impl_->PinchGestureEnd();
1612 host_impl_->ScrollEnd();
1613 EXPECT_FALSE(did_request_animate_);
1614 EXPECT_TRUE(did_request_redraw_);
1615 EXPECT_TRUE(did_request_commit_);
1617 scoped_ptr<ScrollAndScaleSet> scroll_info =
1618 host_impl_->ProcessScrollDeltas();
1619 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1622 // Zoom-in clamping
1624 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1625 max_page_scale);
1626 scroll_layer->SetScrollDelta(gfx::Vector2d());
1627 float page_scale_delta = 10.f;
1629 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1630 host_impl_->PinchGestureBegin();
1631 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1632 host_impl_->PinchGestureEnd();
1633 host_impl_->ScrollEnd();
1635 scoped_ptr<ScrollAndScaleSet> scroll_info =
1636 host_impl_->ProcessScrollDeltas();
1637 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1640 // Zoom-out clamping
1642 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1643 max_page_scale);
1644 scroll_layer->SetScrollDelta(gfx::Vector2d());
1645 scroll_layer->PullDeltaForMainThread();
1646 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1648 float page_scale_delta = 0.1f;
1649 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1650 host_impl_->PinchGestureBegin();
1651 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1652 host_impl_->PinchGestureEnd();
1653 host_impl_->ScrollEnd();
1655 scoped_ptr<ScrollAndScaleSet> scroll_info =
1656 host_impl_->ProcessScrollDeltas();
1657 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1659 EXPECT_TRUE(scroll_info->scrolls.empty());
1662 // Two-finger panning should not happen based on pinch events only
1664 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1665 max_page_scale);
1666 scroll_layer->SetScrollDelta(gfx::Vector2d());
1667 scroll_layer->PullDeltaForMainThread();
1668 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1670 float page_scale_delta = 1.f;
1671 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1672 host_impl_->PinchGestureBegin();
1673 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1674 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1675 host_impl_->PinchGestureEnd();
1676 host_impl_->ScrollEnd();
1678 scoped_ptr<ScrollAndScaleSet> scroll_info =
1679 host_impl_->ProcessScrollDeltas();
1680 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1681 EXPECT_TRUE(scroll_info->scrolls.empty());
1684 // Two-finger panning should work with interleaved scroll events
1686 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1687 max_page_scale);
1688 scroll_layer->SetScrollDelta(gfx::Vector2d());
1689 scroll_layer->PullDeltaForMainThread();
1690 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1692 float page_scale_delta = 1.f;
1693 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1694 host_impl_->PinchGestureBegin();
1695 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1696 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1697 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1698 host_impl_->PinchGestureEnd();
1699 host_impl_->ScrollEnd();
1701 scoped_ptr<ScrollAndScaleSet> scroll_info =
1702 host_impl_->ProcessScrollDeltas();
1703 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1704 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1705 gfx::Vector2d(-10, -10)));
1708 // Two-finger panning should work when starting fully zoomed out.
1710 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1711 scroll_layer->SetScrollDelta(gfx::Vector2d());
1712 scroll_layer->PullDeltaForMainThread();
1713 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1715 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1716 host_impl_->PinchGestureBegin();
1717 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1718 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1719 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1720 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1721 host_impl_->PinchGestureEnd();
1722 host_impl_->ScrollEnd();
1724 scoped_ptr<ScrollAndScaleSet> scroll_info =
1725 host_impl_->ProcessScrollDeltas();
1726 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1727 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1728 gfx::Vector2d(20, 20)));
1732 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1733 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1734 host_impl_->SetViewportSize(gfx::Size(50, 50));
1735 DrawFrame();
1737 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1738 DCHECK(scroll_layer);
1740 float min_page_scale = 0.5f;
1741 float max_page_scale = 4.f;
1742 base::TimeTicks start_time = base::TimeTicks() +
1743 base::TimeDelta::FromSeconds(1);
1744 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1745 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1746 base::TimeTicks end_time = start_time + duration;
1748 BeginFrameArgs begin_frame_args =
1749 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
1751 // Non-anchor zoom-in
1753 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1754 max_page_scale);
1755 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1757 did_request_redraw_ = false;
1758 did_request_animate_ = false;
1759 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1760 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1761 gfx::Vector2d(),
1762 false,
1763 2.f,
1764 duration)));
1765 host_impl_->ActivateSyncTree();
1766 EXPECT_FALSE(did_request_redraw_);
1767 EXPECT_TRUE(did_request_animate_);
1769 did_request_redraw_ = false;
1770 did_request_animate_ = false;
1771 begin_frame_args.frame_time = start_time;
1772 host_impl_->WillBeginImplFrame(begin_frame_args);
1773 host_impl_->Animate();
1774 EXPECT_TRUE(did_request_redraw_);
1775 EXPECT_TRUE(did_request_animate_);
1776 host_impl_->DidFinishImplFrame();
1778 did_request_redraw_ = false;
1779 did_request_animate_ = false;
1780 begin_frame_args.frame_time = halfway_through_animation;
1781 host_impl_->WillBeginImplFrame(begin_frame_args);
1782 host_impl_->Animate();
1783 EXPECT_TRUE(did_request_redraw_);
1784 EXPECT_TRUE(did_request_animate_);
1785 host_impl_->DidFinishImplFrame();
1787 did_request_redraw_ = false;
1788 did_request_animate_ = false;
1789 did_request_commit_ = false;
1790 begin_frame_args.frame_time = end_time;
1791 host_impl_->WillBeginImplFrame(begin_frame_args);
1792 host_impl_->Animate();
1793 EXPECT_TRUE(did_request_commit_);
1794 EXPECT_FALSE(did_request_animate_);
1795 host_impl_->DidFinishImplFrame();
1797 scoped_ptr<ScrollAndScaleSet> scroll_info =
1798 host_impl_->ProcessScrollDeltas();
1799 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1800 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1801 gfx::Vector2d(-50, -50)));
1804 start_time += base::TimeDelta::FromSeconds(10);
1805 halfway_through_animation += base::TimeDelta::FromSeconds(10);
1806 end_time += base::TimeDelta::FromSeconds(10);
1808 // Anchor zoom-out
1810 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1811 max_page_scale);
1812 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1814 did_request_redraw_ = false;
1815 did_request_animate_ = false;
1816 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1817 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1818 gfx::Vector2d(25, 25),
1819 true,
1820 min_page_scale,
1821 duration)));
1822 host_impl_->ActivateSyncTree();
1823 EXPECT_FALSE(did_request_redraw_);
1824 EXPECT_TRUE(did_request_animate_);
1826 did_request_redraw_ = false;
1827 did_request_animate_ = false;
1828 begin_frame_args.frame_time = start_time;
1829 host_impl_->WillBeginImplFrame(begin_frame_args);
1830 host_impl_->Animate();
1831 EXPECT_TRUE(did_request_redraw_);
1832 EXPECT_TRUE(did_request_animate_);
1833 host_impl_->DidFinishImplFrame();
1835 did_request_redraw_ = false;
1836 did_request_commit_ = false;
1837 did_request_animate_ = false;
1838 begin_frame_args.frame_time = end_time;
1839 host_impl_->WillBeginImplFrame(begin_frame_args);
1840 host_impl_->Animate();
1841 EXPECT_TRUE(did_request_redraw_);
1842 EXPECT_FALSE(did_request_animate_);
1843 EXPECT_TRUE(did_request_commit_);
1844 host_impl_->DidFinishImplFrame();
1846 scoped_ptr<ScrollAndScaleSet> scroll_info =
1847 host_impl_->ProcessScrollDeltas();
1848 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1849 // Pushed to (0,0) via clamping against contents layer size.
1850 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1851 gfx::Vector2d(-50, -50)));
1855 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1856 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1857 host_impl_->SetViewportSize(gfx::Size(50, 50));
1858 DrawFrame();
1860 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1861 DCHECK(scroll_layer);
1863 float min_page_scale = 0.5f;
1864 float max_page_scale = 4.f;
1865 base::TimeTicks start_time = base::TimeTicks() +
1866 base::TimeDelta::FromSeconds(1);
1867 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1868 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1869 base::TimeTicks end_time = start_time + duration;
1871 BeginFrameArgs begin_frame_args =
1872 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
1874 // Anchor zoom with unchanged page scale should not change scroll or scale.
1876 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1877 max_page_scale);
1878 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1880 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1881 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1882 gfx::Vector2d(),
1883 true,
1884 1.f,
1885 duration)));
1886 host_impl_->ActivateSyncTree();
1887 begin_frame_args.frame_time = start_time;
1888 host_impl_->WillBeginImplFrame(begin_frame_args);
1889 host_impl_->Animate();
1890 host_impl_->DidFinishImplFrame();
1892 begin_frame_args.frame_time = halfway_through_animation;
1893 host_impl_->WillBeginImplFrame(begin_frame_args);
1894 host_impl_->Animate();
1895 EXPECT_TRUE(did_request_redraw_);
1896 host_impl_->DidFinishImplFrame();
1898 begin_frame_args.frame_time = end_time;
1899 host_impl_->WillBeginImplFrame(begin_frame_args);
1900 host_impl_->Animate();
1901 EXPECT_TRUE(did_request_commit_);
1902 host_impl_->DidFinishImplFrame();
1904 scoped_ptr<ScrollAndScaleSet> scroll_info =
1905 host_impl_->ProcessScrollDeltas();
1906 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1907 ExpectNone(*scroll_info, scroll_layer->id());
1911 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1912 host_impl_->CreatePendingTree();
1913 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
1914 CreateScrollAndContentsLayers(
1915 host_impl_->pending_tree(),
1916 gfx::Size(100, 100));
1917 host_impl_->ActivateSyncTree();
1918 DrawFrame();
1920 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1921 DCHECK(scroll_layer);
1923 float min_page_scale = 0.5f;
1924 float max_page_scale = 4.f;
1925 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1926 max_page_scale);
1927 host_impl_->ActivateSyncTree();
1929 base::TimeTicks start_time = base::TimeTicks() +
1930 base::TimeDelta::FromSeconds(1);
1931 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1932 base::TimeTicks third_through_animation = start_time + duration / 3;
1933 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1934 base::TimeTicks end_time = start_time + duration;
1935 float target_scale = 2.f;
1937 BeginFrameArgs begin_frame_args =
1938 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
1940 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1942 // Make sure TakePageScaleAnimation works properly.
1944 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1945 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1946 gfx::Vector2d(),
1947 false,
1948 target_scale,
1949 duration)));
1950 scoped_ptr<PendingPageScaleAnimation> psa =
1951 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1952 EXPECT_EQ(target_scale, psa->scale);
1953 EXPECT_EQ(duration, psa->duration);
1954 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1956 // Recreate the PSA. Nothing should happen here since the tree containing the
1957 // PSA hasn't been activated yet.
1958 did_request_redraw_ = false;
1959 did_request_animate_ = false;
1960 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1961 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1962 gfx::Vector2d(),
1963 false,
1964 target_scale,
1965 duration)));
1966 begin_frame_args.frame_time = halfway_through_animation;
1967 host_impl_->WillBeginImplFrame(begin_frame_args);
1968 host_impl_->Animate();
1969 EXPECT_FALSE(did_request_animate_);
1970 EXPECT_FALSE(did_request_redraw_);
1971 host_impl_->DidFinishImplFrame();
1973 // Activate the sync tree. This should cause the animation to become enabled.
1974 // It should also clear the pointer on the sync tree.
1975 host_impl_->ActivateSyncTree();
1976 EXPECT_EQ(nullptr,
1977 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1978 EXPECT_FALSE(did_request_redraw_);
1979 EXPECT_TRUE(did_request_animate_);
1981 start_time += base::TimeDelta::FromSeconds(10);
1982 third_through_animation += base::TimeDelta::FromSeconds(10);
1983 halfway_through_animation += base::TimeDelta::FromSeconds(10);
1984 end_time += base::TimeDelta::FromSeconds(10);
1986 // From here on, make sure the animation runs as normal.
1987 did_request_redraw_ = false;
1988 did_request_animate_ = false;
1989 begin_frame_args.frame_time = start_time;
1990 host_impl_->WillBeginImplFrame(begin_frame_args);
1991 host_impl_->Animate();
1992 EXPECT_TRUE(did_request_redraw_);
1993 EXPECT_TRUE(did_request_animate_);
1994 host_impl_->DidFinishImplFrame();
1996 did_request_redraw_ = false;
1997 did_request_animate_ = false;
1998 begin_frame_args.frame_time = third_through_animation;
1999 host_impl_->WillBeginImplFrame(begin_frame_args);
2000 host_impl_->Animate();
2001 EXPECT_TRUE(did_request_redraw_);
2002 EXPECT_TRUE(did_request_animate_);
2003 host_impl_->DidFinishImplFrame();
2005 // Another activation shouldn't have any effect on the animation.
2006 host_impl_->ActivateSyncTree();
2008 did_request_redraw_ = false;
2009 did_request_animate_ = false;
2010 begin_frame_args.frame_time = halfway_through_animation;
2011 host_impl_->WillBeginImplFrame(begin_frame_args);
2012 host_impl_->Animate();
2013 EXPECT_TRUE(did_request_redraw_);
2014 EXPECT_TRUE(did_request_animate_);
2015 host_impl_->DidFinishImplFrame();
2017 did_request_redraw_ = false;
2018 did_request_animate_ = false;
2019 did_request_commit_ = false;
2020 begin_frame_args.frame_time = end_time;
2021 host_impl_->WillBeginImplFrame(begin_frame_args);
2022 host_impl_->Animate();
2023 EXPECT_TRUE(did_request_commit_);
2024 EXPECT_FALSE(did_request_animate_);
2025 host_impl_->DidFinishImplFrame();
2027 scoped_ptr<ScrollAndScaleSet> scroll_info =
2028 host_impl_->ProcessScrollDeltas();
2029 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
2030 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
2031 gfx::Vector2d(-50, -50)));
2034 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
2035 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2036 host_impl_->SetViewportSize(gfx::Size(50, 50));
2037 DrawFrame();
2039 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
2040 DCHECK(scroll_layer);
2042 base::TimeTicks start_time =
2043 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
2044 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
2045 base::TimeTicks halfway_through_animation = start_time + duration / 2;
2046 base::TimeTicks end_time = start_time + duration;
2048 BeginFrameArgs begin_frame_args =
2049 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
2051 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
2052 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
2054 did_complete_page_scale_animation_ = false;
2055 host_impl_->active_tree()->SetPendingPageScaleAnimation(
2056 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
2057 gfx::Vector2d(), false, 2.f, duration)));
2058 host_impl_->ActivateSyncTree();
2059 begin_frame_args.frame_time = start_time;
2060 host_impl_->WillBeginImplFrame(begin_frame_args);
2061 host_impl_->Animate();
2062 EXPECT_FALSE(did_complete_page_scale_animation_);
2063 host_impl_->DidFinishImplFrame();
2065 begin_frame_args.frame_time = halfway_through_animation;
2066 host_impl_->WillBeginImplFrame(begin_frame_args);
2067 host_impl_->Animate();
2068 EXPECT_FALSE(did_complete_page_scale_animation_);
2069 host_impl_->DidFinishImplFrame();
2071 begin_frame_args.frame_time = end_time;
2072 host_impl_->WillBeginImplFrame(begin_frame_args);
2073 host_impl_->Animate();
2074 EXPECT_TRUE(did_complete_page_scale_animation_);
2075 host_impl_->DidFinishImplFrame();
2078 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
2079 public:
2080 LayerTreeHostImplOverridePhysicalTime(
2081 const LayerTreeSettings& settings,
2082 LayerTreeHostImplClient* client,
2083 Proxy* proxy,
2084 SharedBitmapManager* manager,
2085 TaskGraphRunner* task_graph_runner,
2086 RenderingStatsInstrumentation* rendering_stats_instrumentation)
2087 : LayerTreeHostImpl(settings,
2088 client,
2089 proxy,
2090 rendering_stats_instrumentation,
2091 manager,
2092 nullptr,
2093 task_graph_runner,
2094 0) {}
2096 BeginFrameArgs CurrentBeginFrameArgs() const override {
2097 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
2098 fake_current_physical_time_);
2101 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
2102 fake_current_physical_time_ = fake_now;
2105 private:
2106 base::TimeTicks fake_current_physical_time_;
2109 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
2110 protected:
2111 void SetupLayers(LayerTreeSettings settings) {
2112 gfx::Size content_size(100, 100);
2114 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
2115 new LayerTreeHostImplOverridePhysicalTime(
2116 settings, this, &proxy_, &shared_bitmap_manager_,
2117 &task_graph_runner_, &stats_instrumentation_);
2118 host_impl_ = make_scoped_ptr(host_impl_override_time);
2119 host_impl_->InitializeRenderer(CreateOutputSurface());
2121 SetupScrollAndContentsLayers(content_size);
2122 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
2123 host_impl_->SetViewportSize(
2124 gfx::Size(content_size.width() / 2, content_size.height() / 2));
2126 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
2127 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 400,
2128 VERTICAL, 10, 0, false, true);
2129 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
2131 LayerImpl* scroll = host_impl_->InnerViewportScrollLayer();
2132 LayerImpl* root = scroll->parent()->parent();
2133 scrollbar->SetScrollLayerAndClipLayerByIds(scroll->id(), root->id());
2134 root->AddChild(scrollbar.Pass());
2136 host_impl_->active_tree()->DidBecomeActive();
2137 DrawFrame();
2140 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
2141 LayerTreeSettings settings;
2142 settings.scrollbar_animator = animator;
2143 settings.scrollbar_fade_delay_ms = 20;
2144 settings.scrollbar_fade_duration_ms = 20;
2146 SetupLayers(settings);
2148 base::TimeTicks fake_now = base::TimeTicks::Now();
2150 EXPECT_FALSE(did_request_animate_);
2151 EXPECT_FALSE(did_request_redraw_);
2152 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2153 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2155 // If no scroll happened during a scroll gesture, it should have no effect.
2156 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2157 host_impl_->ScrollEnd();
2158 EXPECT_FALSE(did_request_animate_);
2159 EXPECT_FALSE(did_request_redraw_);
2160 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2161 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2163 // After a scroll, a scrollbar animation should be scheduled about 20ms from
2164 // now.
2165 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2166 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2167 EXPECT_FALSE(did_request_animate_);
2168 EXPECT_TRUE(did_request_redraw_);
2169 did_request_redraw_ = false;
2170 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2171 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2173 host_impl_->ScrollEnd();
2174 EXPECT_FALSE(did_request_animate_);
2175 EXPECT_FALSE(did_request_redraw_);
2176 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2177 requested_animation_delay_);
2178 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2180 fake_now += requested_animation_delay_;
2181 requested_animation_delay_ = base::TimeDelta();
2182 animation_task_.Run();
2183 animation_task_ = base::Closure();
2184 EXPECT_TRUE(did_request_animate_);
2185 did_request_animate_ = false;
2186 EXPECT_FALSE(did_request_redraw_);
2188 // After the scrollbar animation begins, we should start getting redraws.
2189 BeginFrameArgs begin_frame_args =
2190 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, fake_now);
2191 host_impl_->WillBeginImplFrame(begin_frame_args);
2192 host_impl_->Animate();
2193 EXPECT_TRUE(did_request_animate_);
2194 did_request_animate_ = false;
2195 EXPECT_TRUE(did_request_redraw_);
2196 did_request_redraw_ = false;
2197 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2198 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2199 host_impl_->DidFinishImplFrame();
2201 // Setting the scroll offset outside a scroll should also cause the
2202 // scrollbar to appear and to schedule a scrollbar animation.
2203 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2204 gfx::ScrollOffset(5, 5));
2205 EXPECT_FALSE(did_request_animate_);
2206 EXPECT_FALSE(did_request_redraw_);
2207 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2208 requested_animation_delay_);
2209 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2210 requested_animation_delay_ = base::TimeDelta();
2211 animation_task_ = base::Closure();
2213 // Scrollbar animation is not triggered unnecessarily.
2214 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2215 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2216 EXPECT_FALSE(did_request_animate_);
2217 EXPECT_TRUE(did_request_redraw_);
2218 did_request_redraw_ = false;
2219 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2220 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2222 host_impl_->ScrollEnd();
2223 EXPECT_FALSE(did_request_animate_);
2224 EXPECT_FALSE(did_request_redraw_);
2225 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2226 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2228 // Changing page scale triggers scrollbar animation.
2229 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
2230 host_impl_->SetPageScaleOnActiveTree(1.1f);
2231 EXPECT_FALSE(did_request_animate_);
2232 EXPECT_FALSE(did_request_redraw_);
2233 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2234 requested_animation_delay_);
2235 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2236 requested_animation_delay_ = base::TimeDelta();
2237 animation_task_ = base::Closure();
2241 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
2242 RunTest(LayerTreeSettings::LINEAR_FADE);
2245 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
2246 RunTest(LayerTreeSettings::THINNING);
2249 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2250 float device_scale_factor) {
2251 LayerTreeSettings settings;
2252 settings.scrollbar_fade_delay_ms = 500;
2253 settings.scrollbar_fade_duration_ms = 300;
2254 settings.scrollbar_animator = LayerTreeSettings::THINNING;
2256 gfx::Size viewport_size(300, 200);
2257 gfx::Size device_viewport_size = gfx::ToFlooredSize(
2258 gfx::ScaleSize(viewport_size, device_scale_factor));
2259 gfx::Size content_size(1000, 1000);
2261 CreateHostImpl(settings, CreateOutputSurface());
2262 host_impl_->SetDeviceScaleFactor(device_scale_factor);
2263 host_impl_->SetViewportSize(device_viewport_size);
2265 scoped_ptr<LayerImpl> root =
2266 LayerImpl::Create(host_impl_->active_tree(), 1);
2267 root->SetBounds(viewport_size);
2268 root->SetHasRenderSurface(true);
2270 scoped_ptr<LayerImpl> scroll =
2271 LayerImpl::Create(host_impl_->active_tree(), 2);
2272 scroll->SetScrollClipLayer(root->id());
2273 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2274 scroll->SetBounds(content_size);
2275 scroll->SetIsContainerForFixedPositionLayers(true);
2277 scoped_ptr<LayerImpl> contents =
2278 LayerImpl::Create(host_impl_->active_tree(), 3);
2279 contents->SetDrawsContent(true);
2280 contents->SetBounds(content_size);
2282 // The scrollbar is on the right side.
2283 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
2284 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
2285 scrollbar->SetDrawsContent(true);
2286 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
2287 scrollbar->SetPosition(gfx::Point(285, 0));
2289 scroll->AddChild(contents.Pass());
2290 root->AddChild(scroll.Pass());
2291 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
2292 root->AddChild(scrollbar.Pass());
2294 host_impl_->active_tree()->SetRootLayer(root.Pass());
2295 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
2296 Layer::INVALID_ID);
2297 host_impl_->active_tree()->DidBecomeActive();
2298 DrawFrame();
2300 LayerImpl* root_scroll =
2301 host_impl_->active_tree()->InnerViewportScrollLayer();
2302 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
2303 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
2304 static_cast<ScrollbarAnimationControllerThinning*>(
2305 root_scroll->scrollbar_animation_controller());
2306 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
2308 host_impl_->MouseMoveAt(gfx::Point(1, 1));
2309 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2311 host_impl_->MouseMoveAt(gfx::Point(200, 50));
2312 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2314 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2315 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2317 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
2318 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2319 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2321 did_request_redraw_ = false;
2322 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2323 host_impl_->MouseMoveAt(gfx::Point(290, 100));
2324 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2325 host_impl_->MouseMoveAt(gfx::Point(290, 120));
2326 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2327 host_impl_->MouseMoveAt(gfx::Point(150, 120));
2328 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2331 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
2332 SetupMouseMoveAtWithDeviceScale(1.f);
2335 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
2336 SetupMouseMoveAtWithDeviceScale(2.f);
2339 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
2340 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2341 host_impl_->SetViewportSize(gfx::Size(50, 50));
2342 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
2343 DrawFrame();
2345 CompositorFrameMetadata metadata =
2346 host_impl_->MakeCompositorFrameMetadata();
2347 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
2348 EXPECT_EQ(1.f, metadata.page_scale_factor);
2349 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
2350 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2351 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2352 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2353 EXPECT_FALSE(metadata.root_overflow_x_hidden);
2354 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2357 // Scrolling should update metadata immediately.
2358 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2359 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2360 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2362 CompositorFrameMetadata metadata =
2363 host_impl_->MakeCompositorFrameMetadata();
2364 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2366 host_impl_->ScrollEnd();
2368 CompositorFrameMetadata metadata =
2369 host_impl_->MakeCompositorFrameMetadata();
2370 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2373 // Root "overflow: hidden" properties should be reflected on the outer
2374 // viewport scroll layer.
2376 host_impl_->active_tree()
2377 ->OuterViewportScrollLayer()
2378 ->set_user_scrollable_horizontal(false);
2379 CompositorFrameMetadata metadata =
2380 host_impl_->MakeCompositorFrameMetadata();
2381 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2382 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2384 host_impl_->active_tree()
2385 ->OuterViewportScrollLayer()
2386 ->set_user_scrollable_vertical(false);
2387 metadata = host_impl_->MakeCompositorFrameMetadata();
2388 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2389 EXPECT_TRUE(metadata.root_overflow_y_hidden);
2392 // Re-enable scrollability and verify that overflows are no longer hidden.
2394 host_impl_->active_tree()
2395 ->OuterViewportScrollLayer()
2396 ->set_user_scrollable_horizontal(true);
2397 host_impl_->active_tree()
2398 ->OuterViewportScrollLayer()
2399 ->set_user_scrollable_vertical(true);
2400 CompositorFrameMetadata metadata =
2401 host_impl_->MakeCompositorFrameMetadata();
2402 EXPECT_FALSE(metadata.root_overflow_x_hidden);
2403 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2406 // Root "overflow: hidden" properties should also be reflected on the
2407 // inner viewport scroll layer.
2409 host_impl_->active_tree()
2410 ->InnerViewportScrollLayer()
2411 ->set_user_scrollable_horizontal(false);
2412 CompositorFrameMetadata metadata =
2413 host_impl_->MakeCompositorFrameMetadata();
2414 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2415 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2417 host_impl_->active_tree()
2418 ->InnerViewportScrollLayer()
2419 ->set_user_scrollable_vertical(false);
2420 metadata = host_impl_->MakeCompositorFrameMetadata();
2421 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2422 EXPECT_TRUE(metadata.root_overflow_y_hidden);
2425 // Page scale should update metadata correctly (shrinking only the viewport).
2426 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
2427 host_impl_->PinchGestureBegin();
2428 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
2429 host_impl_->PinchGestureEnd();
2430 host_impl_->ScrollEnd();
2432 CompositorFrameMetadata metadata =
2433 host_impl_->MakeCompositorFrameMetadata();
2434 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2435 EXPECT_EQ(2.f, metadata.page_scale_factor);
2436 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
2437 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2438 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2439 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2442 // Likewise if set from the main thread.
2443 host_impl_->ProcessScrollDeltas();
2444 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
2445 host_impl_->SetPageScaleOnActiveTree(4.f);
2447 CompositorFrameMetadata metadata =
2448 host_impl_->MakeCompositorFrameMetadata();
2449 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2450 EXPECT_EQ(4.f, metadata.page_scale_factor);
2451 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
2452 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2453 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2454 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2458 class DidDrawCheckLayer : public LayerImpl {
2459 public:
2460 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
2461 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
2464 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
2465 will_draw_called_ = true;
2466 if (will_draw_returns_false_)
2467 return false;
2468 return LayerImpl::WillDraw(draw_mode, provider);
2471 void AppendQuads(RenderPass* render_pass,
2472 AppendQuadsData* append_quads_data) override {
2473 append_quads_called_ = true;
2474 LayerImpl::AppendQuads(render_pass, append_quads_data);
2477 void DidDraw(ResourceProvider* provider) override {
2478 did_draw_called_ = true;
2479 LayerImpl::DidDraw(provider);
2482 bool will_draw_called() const { return will_draw_called_; }
2483 bool append_quads_called() const { return append_quads_called_; }
2484 bool did_draw_called() const { return did_draw_called_; }
2486 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
2488 void ClearDidDrawCheck() {
2489 will_draw_called_ = false;
2490 append_quads_called_ = false;
2491 did_draw_called_ = false;
2494 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
2496 void AddCopyRequest() {
2497 ScopedPtrVector<CopyOutputRequest> requests;
2498 requests.push_back(
2499 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
2500 SetHasRenderSurface(true);
2501 PassCopyRequests(&requests);
2504 protected:
2505 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
2506 : LayerImpl(tree_impl, id),
2507 will_draw_returns_false_(false),
2508 will_draw_called_(false),
2509 append_quads_called_(false),
2510 did_draw_called_(false) {
2511 SetBounds(gfx::Size(10, 10));
2512 SetDrawsContent(true);
2513 draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10);
2516 private:
2517 bool will_draw_returns_false_;
2518 bool will_draw_called_;
2519 bool append_quads_called_;
2520 bool did_draw_called_;
2523 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
2524 // The root layer is always drawn, so run this test on a child layer that
2525 // will be masked out by the root layer's bounds.
2526 host_impl_->active_tree()->SetRootLayer(
2527 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2528 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2529 host_impl_->active_tree()->root_layer());
2531 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2532 root->SetHasRenderSurface(true);
2533 DidDrawCheckLayer* layer =
2534 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2537 LayerTreeHostImpl::FrameData frame;
2538 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2539 host_impl_->DrawLayers(&frame);
2540 host_impl_->DidDrawAllLayers(frame);
2542 EXPECT_TRUE(layer->will_draw_called());
2543 EXPECT_TRUE(layer->append_quads_called());
2544 EXPECT_TRUE(layer->did_draw_called());
2547 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
2550 LayerTreeHostImpl::FrameData frame;
2552 layer->set_will_draw_returns_false();
2553 layer->ClearDidDrawCheck();
2555 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2556 host_impl_->DrawLayers(&frame);
2557 host_impl_->DidDrawAllLayers(frame);
2559 EXPECT_TRUE(layer->will_draw_called());
2560 EXPECT_FALSE(layer->append_quads_called());
2561 EXPECT_FALSE(layer->did_draw_called());
2565 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
2566 // The root layer is always drawn, so run this test on a child layer that
2567 // will be masked out by the root layer's bounds.
2568 host_impl_->active_tree()->SetRootLayer(
2569 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2570 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2571 host_impl_->active_tree()->root_layer());
2572 root->SetMasksToBounds(true);
2573 root->SetHasRenderSurface(true);
2574 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2575 DidDrawCheckLayer* layer =
2576 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2577 // Ensure visible_layer_rect for layer is empty.
2578 layer->SetPosition(gfx::PointF(100.f, 100.f));
2579 layer->SetBounds(gfx::Size(10, 10));
2581 LayerTreeHostImpl::FrameData frame;
2583 EXPECT_FALSE(layer->will_draw_called());
2584 EXPECT_FALSE(layer->did_draw_called());
2586 host_impl_->active_tree()->BuildPropertyTreesForTesting();
2587 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2588 host_impl_->DrawLayers(&frame);
2589 host_impl_->DidDrawAllLayers(frame);
2591 EXPECT_FALSE(layer->will_draw_called());
2592 EXPECT_FALSE(layer->did_draw_called());
2594 EXPECT_TRUE(layer->visible_layer_rect().IsEmpty());
2596 // Ensure visible_layer_rect for layer is not empty
2597 layer->SetPosition(gfx::PointF());
2599 EXPECT_FALSE(layer->will_draw_called());
2600 EXPECT_FALSE(layer->did_draw_called());
2602 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2603 host_impl_->DrawLayers(&frame);
2604 host_impl_->DidDrawAllLayers(frame);
2606 EXPECT_TRUE(layer->will_draw_called());
2607 EXPECT_TRUE(layer->did_draw_called());
2609 EXPECT_FALSE(layer->visible_layer_rect().IsEmpty());
2612 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
2613 gfx::Size big_size(1000, 1000);
2614 host_impl_->SetViewportSize(big_size);
2616 host_impl_->active_tree()->SetRootLayer(
2617 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2618 DidDrawCheckLayer* root =
2619 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2621 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2622 DidDrawCheckLayer* occluded_layer =
2623 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2625 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2626 root->SetHasRenderSurface(true);
2627 DidDrawCheckLayer* top_layer =
2628 static_cast<DidDrawCheckLayer*>(root->children()[1]);
2629 // This layer covers the occluded_layer above. Make this layer large so it can
2630 // occlude.
2631 top_layer->SetBounds(big_size);
2632 top_layer->SetContentsOpaque(true);
2634 LayerTreeHostImpl::FrameData frame;
2636 EXPECT_FALSE(occluded_layer->will_draw_called());
2637 EXPECT_FALSE(occluded_layer->did_draw_called());
2638 EXPECT_FALSE(top_layer->will_draw_called());
2639 EXPECT_FALSE(top_layer->did_draw_called());
2641 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2642 host_impl_->DrawLayers(&frame);
2643 host_impl_->DidDrawAllLayers(frame);
2645 EXPECT_FALSE(occluded_layer->will_draw_called());
2646 EXPECT_FALSE(occluded_layer->did_draw_called());
2647 EXPECT_TRUE(top_layer->will_draw_called());
2648 EXPECT_TRUE(top_layer->did_draw_called());
2651 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
2652 host_impl_->active_tree()->SetRootLayer(
2653 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2654 DidDrawCheckLayer* root =
2655 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2657 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2658 root->SetHasRenderSurface(true);
2659 DidDrawCheckLayer* layer1 =
2660 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2662 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2663 DidDrawCheckLayer* layer2 =
2664 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
2666 layer1->SetHasRenderSurface(true);
2667 layer1->SetShouldFlattenTransform(true);
2669 EXPECT_FALSE(root->did_draw_called());
2670 EXPECT_FALSE(layer1->did_draw_called());
2671 EXPECT_FALSE(layer2->did_draw_called());
2673 LayerTreeHostImpl::FrameData frame;
2674 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2675 host_impl_->active_tree()->root_layer());
2676 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2677 host_impl_->DrawLayers(&frame);
2678 host_impl_->DidDrawAllLayers(frame);
2680 EXPECT_TRUE(root->did_draw_called());
2681 EXPECT_TRUE(layer1->did_draw_called());
2682 EXPECT_TRUE(layer2->did_draw_called());
2684 EXPECT_NE(root->render_surface(), layer1->render_surface());
2685 EXPECT_TRUE(layer1->render_surface());
2688 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
2689 public:
2690 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2691 int id,
2692 bool tile_missing,
2693 bool had_incomplete_tile,
2694 bool animating,
2695 ResourceProvider* resource_provider) {
2696 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
2698 tile_missing,
2699 had_incomplete_tile,
2700 animating,
2701 resource_provider));
2704 void AppendQuads(RenderPass* render_pass,
2705 AppendQuadsData* append_quads_data) override {
2706 LayerImpl::AppendQuads(render_pass, append_quads_data);
2707 if (had_incomplete_tile_)
2708 append_quads_data->num_incomplete_tiles++;
2709 if (tile_missing_)
2710 append_quads_data->num_missing_tiles++;
2713 private:
2714 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
2715 int id,
2716 bool tile_missing,
2717 bool had_incomplete_tile,
2718 bool animating,
2719 ResourceProvider* resource_provider)
2720 : DidDrawCheckLayer(tree_impl, id),
2721 tile_missing_(tile_missing),
2722 had_incomplete_tile_(had_incomplete_tile) {
2723 if (animating)
2724 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2727 bool tile_missing_;
2728 bool had_incomplete_tile_;
2731 struct PrepareToDrawSuccessTestCase {
2732 struct State {
2733 bool has_missing_tile = false;
2734 bool has_incomplete_tile = false;
2735 bool is_animating = false;
2736 bool has_copy_request = false;
2738 bool high_res_required = false;
2739 State layer_before;
2740 State layer_between;
2741 State layer_after;
2742 DrawResult expected_result;
2744 explicit PrepareToDrawSuccessTestCase(DrawResult result)
2745 : expected_result(result) {}
2748 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
2749 std::vector<PrepareToDrawSuccessTestCase> cases;
2751 // 0. Default case.
2752 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2753 // 1. Animated layer first.
2754 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2755 cases.back().layer_before.is_animating = true;
2756 // 2. Animated layer between.
2757 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2758 cases.back().layer_between.is_animating = true;
2759 // 3. Animated layer last.
2760 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2761 cases.back().layer_after.is_animating = true;
2762 // 4. Missing tile first.
2763 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2764 cases.back().layer_before.has_missing_tile = true;
2765 // 5. Missing tile between.
2766 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2767 cases.back().layer_between.has_missing_tile = true;
2768 // 6. Missing tile last.
2769 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2770 cases.back().layer_after.has_missing_tile = true;
2771 // 7. Incomplete tile first.
2772 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2773 cases.back().layer_before.has_incomplete_tile = true;
2774 // 8. Incomplete tile between.
2775 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2776 cases.back().layer_between.has_incomplete_tile = true;
2777 // 9. Incomplete tile last.
2778 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2779 cases.back().layer_after.has_incomplete_tile = true;
2780 // 10. Animation with missing tile.
2781 cases.push_back(
2782 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
2783 cases.back().layer_between.has_missing_tile = true;
2784 cases.back().layer_between.is_animating = true;
2785 // 11. Animation with incomplete tile.
2786 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2787 cases.back().layer_between.has_incomplete_tile = true;
2788 cases.back().layer_between.is_animating = true;
2790 // 12. High res required.
2791 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2792 cases.back().high_res_required = true;
2793 // 13. High res required with incomplete tile.
2794 cases.push_back(
2795 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2796 cases.back().high_res_required = true;
2797 cases.back().layer_between.has_incomplete_tile = true;
2798 // 14. High res required with missing tile.
2799 cases.push_back(
2800 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2801 cases.back().high_res_required = true;
2802 cases.back().layer_between.has_missing_tile = true;
2804 // 15. High res required is higher priority than animating missing tiles.
2805 cases.push_back(
2806 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2807 cases.back().high_res_required = true;
2808 cases.back().layer_between.has_missing_tile = true;
2809 cases.back().layer_after.has_missing_tile = true;
2810 cases.back().layer_after.is_animating = true;
2811 // 16. High res required is higher priority than animating missing tiles.
2812 cases.push_back(
2813 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2814 cases.back().high_res_required = true;
2815 cases.back().layer_between.has_missing_tile = true;
2816 cases.back().layer_before.has_missing_tile = true;
2817 cases.back().layer_before.is_animating = true;
2819 host_impl_->active_tree()->SetRootLayer(
2820 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2821 DidDrawCheckLayer* root =
2822 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2823 root->SetHasRenderSurface(true);
2825 LayerTreeHostImpl::FrameData frame;
2826 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2827 host_impl_->DrawLayers(&frame);
2828 host_impl_->DidDrawAllLayers(frame);
2829 host_impl_->SwapBuffers(frame);
2831 for (size_t i = 0; i < cases.size(); ++i) {
2832 const auto& testcase = cases[i];
2833 std::vector<LayerImpl*> to_remove;
2834 for (auto* child : root->children())
2835 to_remove.push_back(child);
2836 for (auto* child : to_remove)
2837 root->RemoveChild(child);
2839 std::ostringstream scope;
2840 scope << "Test case: " << i;
2841 SCOPED_TRACE(scope.str());
2843 root->AddChild(MissingTextureAnimatingLayer::Create(
2844 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2845 testcase.layer_before.has_incomplete_tile,
2846 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2847 DidDrawCheckLayer* before =
2848 static_cast<DidDrawCheckLayer*>(root->children().back());
2849 if (testcase.layer_before.has_copy_request)
2850 before->AddCopyRequest();
2852 root->AddChild(MissingTextureAnimatingLayer::Create(
2853 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2854 testcase.layer_between.has_incomplete_tile,
2855 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2856 DidDrawCheckLayer* between =
2857 static_cast<DidDrawCheckLayer*>(root->children().back());
2858 if (testcase.layer_between.has_copy_request)
2859 between->AddCopyRequest();
2861 root->AddChild(MissingTextureAnimatingLayer::Create(
2862 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2863 testcase.layer_after.has_incomplete_tile,
2864 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2865 DidDrawCheckLayer* after =
2866 static_cast<DidDrawCheckLayer*>(root->children().back());
2867 if (testcase.layer_after.has_copy_request)
2868 after->AddCopyRequest();
2870 if (testcase.high_res_required)
2871 host_impl_->SetRequiresHighResToDraw();
2873 LayerTreeHostImpl::FrameData frame;
2874 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2875 host_impl_->DrawLayers(&frame);
2876 host_impl_->DidDrawAllLayers(frame);
2877 host_impl_->SwapBuffers(frame);
2881 TEST_F(LayerTreeHostImplTest,
2882 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
2883 CreateHostImpl(DefaultSettings(),
2884 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2885 EXPECT_TRUE(host_impl_->output_surface()
2886 ->capabilities()
2887 .draw_and_swap_full_viewport_every_frame);
2889 std::vector<PrepareToDrawSuccessTestCase> cases;
2891 // 0. Default case.
2892 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2893 // 1. Animation with missing tile.
2894 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2895 cases.back().layer_between.has_missing_tile = true;
2896 cases.back().layer_between.is_animating = true;
2897 // 2. High res required with incomplete tile.
2898 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2899 cases.back().high_res_required = true;
2900 cases.back().layer_between.has_incomplete_tile = true;
2901 // 3. High res required with missing tile.
2902 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2903 cases.back().high_res_required = true;
2904 cases.back().layer_between.has_missing_tile = true;
2906 host_impl_->active_tree()->SetRootLayer(
2907 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2908 DidDrawCheckLayer* root =
2909 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2910 root->SetHasRenderSurface(true);
2912 LayerTreeHostImpl::FrameData frame;
2913 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2914 host_impl_->DrawLayers(&frame);
2915 host_impl_->DidDrawAllLayers(frame);
2916 host_impl_->SwapBuffers(frame);
2918 for (size_t i = 0; i < cases.size(); ++i) {
2919 const auto& testcase = cases[i];
2920 std::vector<LayerImpl*> to_remove;
2921 for (auto* child : root->children())
2922 to_remove.push_back(child);
2923 for (auto* child : to_remove)
2924 root->RemoveChild(child);
2926 std::ostringstream scope;
2927 scope << "Test case: " << i;
2928 SCOPED_TRACE(scope.str());
2930 root->AddChild(MissingTextureAnimatingLayer::Create(
2931 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2932 testcase.layer_before.has_incomplete_tile,
2933 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2934 DidDrawCheckLayer* before =
2935 static_cast<DidDrawCheckLayer*>(root->children().back());
2936 if (testcase.layer_before.has_copy_request)
2937 before->AddCopyRequest();
2939 root->AddChild(MissingTextureAnimatingLayer::Create(
2940 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2941 testcase.layer_between.has_incomplete_tile,
2942 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2943 DidDrawCheckLayer* between =
2944 static_cast<DidDrawCheckLayer*>(root->children().back());
2945 if (testcase.layer_between.has_copy_request)
2946 between->AddCopyRequest();
2948 root->AddChild(MissingTextureAnimatingLayer::Create(
2949 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2950 testcase.layer_after.has_incomplete_tile,
2951 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2952 DidDrawCheckLayer* after =
2953 static_cast<DidDrawCheckLayer*>(root->children().back());
2954 if (testcase.layer_after.has_copy_request)
2955 after->AddCopyRequest();
2957 if (testcase.high_res_required)
2958 host_impl_->SetRequiresHighResToDraw();
2960 LayerTreeHostImpl::FrameData frame;
2961 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2962 host_impl_->DrawLayers(&frame);
2963 host_impl_->DidDrawAllLayers(frame);
2964 host_impl_->SwapBuffers(frame);
2968 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2969 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2970 root->SetScrollClipLayer(Layer::INVALID_ID);
2971 root->SetHasRenderSurface(true);
2972 host_impl_->active_tree()->SetRootLayer(root.Pass());
2973 DrawFrame();
2975 // Scroll event is ignored because layer is not scrollable.
2976 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
2977 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2978 EXPECT_FALSE(did_request_redraw_);
2979 EXPECT_FALSE(did_request_commit_);
2982 TEST_F(LayerTreeHostImplTest, ClampingAfterActivation) {
2983 host_impl_->CreatePendingTree();
2984 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
2985 CreateScrollAndContentsLayers(host_impl_->pending_tree(),
2986 gfx::Size(100, 100));
2987 host_impl_->ActivateSyncTree();
2989 host_impl_->CreatePendingTree();
2990 const gfx::ScrollOffset pending_scroll = gfx::ScrollOffset(-100, -100);
2991 LayerImpl* active_outer_layer =
2992 host_impl_->active_tree()->OuterViewportScrollLayer();
2993 LayerImpl* pending_outer_layer =
2994 host_impl_->pending_tree()->OuterViewportScrollLayer();
2995 pending_outer_layer->PushScrollOffsetFromMainThread(pending_scroll);
2997 host_impl_->ActivateSyncTree();
2998 // Scrolloffsets on the active tree will be clamped after activation.
2999 EXPECT_EQ(active_outer_layer->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
3002 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
3003 public:
3004 LayerTreeHostImplTopControlsTest()
3005 // Make the clip size the same as the layer (content) size so the layer is
3006 // non-scrollable.
3007 : layer_size_(10, 10),
3008 clip_size_(layer_size_),
3009 top_controls_height_(50) {
3010 viewport_size_ = gfx::Size(clip_size_.width(),
3011 clip_size_.height() + top_controls_height_);
3014 bool CreateHostImpl(const LayerTreeSettings& settings,
3015 scoped_ptr<OutputSurface> output_surface) override {
3016 bool init =
3017 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
3018 if (init) {
3019 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
3020 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
3021 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
3023 return init;
3026 void SetupTopControlsAndScrollLayerWithVirtualViewport(
3027 const gfx::Size& inner_viewport_size,
3028 const gfx::Size& outer_viewport_size,
3029 const gfx::Size& scroll_layer_size) {
3030 CreateHostImpl(settings_, CreateOutputSurface());
3031 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
3032 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
3033 host_impl_->DidChangeTopControlsPosition();
3035 scoped_ptr<LayerImpl> root =
3036 LayerImpl::Create(host_impl_->active_tree(), 1);
3037 scoped_ptr<LayerImpl> root_clip =
3038 LayerImpl::Create(host_impl_->active_tree(), 2);
3039 scoped_ptr<LayerImpl> page_scale =
3040 LayerImpl::Create(host_impl_->active_tree(), 3);
3042 scoped_ptr<LayerImpl> outer_scroll =
3043 LayerImpl::Create(host_impl_->active_tree(), 4);
3044 scoped_ptr<LayerImpl> outer_clip =
3045 LayerImpl::Create(host_impl_->active_tree(), 5);
3047 root_clip->SetBounds(inner_viewport_size);
3048 root->SetScrollClipLayer(root_clip->id());
3049 root->SetBounds(outer_viewport_size);
3050 root->SetPosition(gfx::PointF());
3051 root->SetDrawsContent(false);
3052 root->SetIsContainerForFixedPositionLayers(true);
3053 root_clip->SetHasRenderSurface(true);
3054 outer_clip->SetBounds(outer_viewport_size);
3055 outer_scroll->SetScrollClipLayer(outer_clip->id());
3056 outer_scroll->SetBounds(scroll_layer_size);
3057 outer_scroll->SetPosition(gfx::PointF());
3058 outer_scroll->SetDrawsContent(false);
3059 outer_scroll->SetIsContainerForFixedPositionLayers(true);
3061 int inner_viewport_scroll_layer_id = root->id();
3062 int outer_viewport_scroll_layer_id = outer_scroll->id();
3063 int page_scale_layer_id = page_scale->id();
3065 outer_clip->AddChild(outer_scroll.Pass());
3066 root->AddChild(outer_clip.Pass());
3067 page_scale->AddChild(root.Pass());
3068 root_clip->AddChild(page_scale.Pass());
3070 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3071 host_impl_->active_tree()->SetViewportLayersFromIds(
3072 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
3073 outer_viewport_scroll_layer_id);
3075 host_impl_->SetViewportSize(inner_viewport_size);
3076 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3077 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
3080 protected:
3081 gfx::Size layer_size_;
3082 gfx::Size clip_size_;
3083 gfx::Size viewport_size_;
3084 float top_controls_height_;
3086 LayerTreeSettings settings_;
3087 }; // class LayerTreeHostImplTopControlsTest
3089 // Tests that, on a page with content the same size as the viewport, hiding
3090 // the top controls also increases the ScrollableSize (i.e. the content size).
3091 // Since the viewport got larger, the effective scrollable "content" also did.
3092 // This ensures, for one thing, that the overscroll glow is shown in the right
3093 // place.
3094 TEST_F(LayerTreeHostImplTopControlsTest,
3095 HidingTopControlsExpandsScrollableSize) {
3096 SetupTopControlsAndScrollLayerWithVirtualViewport(
3097 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
3099 LayerTreeImpl* active_tree = host_impl_->active_tree();
3101 // Create a content layer beneath the outer viewport scroll layer.
3102 int id = host_impl_->OuterViewportScrollLayer()->id();
3103 host_impl_->OuterViewportScrollLayer()->AddChild(
3104 LayerImpl::Create(host_impl_->active_tree(), id + 2));
3105 LayerImpl* content = active_tree->OuterViewportScrollLayer()->children()[0];
3106 content->SetBounds(gfx::Size(50, 50));
3108 DrawFrame();
3110 LayerImpl* inner_container = active_tree->InnerViewportContainerLayer();
3111 LayerImpl* outer_container = active_tree->OuterViewportContainerLayer();
3113 // The top controls should start off showing so the viewport should be shrunk.
3114 ASSERT_EQ(gfx::Size(50, 50), inner_container->bounds());
3115 ASSERT_EQ(gfx::Size(50, 50), outer_container->bounds());
3117 EXPECT_EQ(gfx::SizeF(50, 50), active_tree->ScrollableSize());
3119 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3120 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3122 host_impl_->top_controls_manager()->ScrollBegin();
3124 // Hide the top controls by a bit, the scrollable size should increase but the
3125 // actual content bounds shouldn't.
3127 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
3128 ASSERT_EQ(gfx::Size(50, 75), inner_container->bounds());
3129 ASSERT_EQ(gfx::Size(50, 75), outer_container->bounds());
3130 EXPECT_EQ(gfx::SizeF(50, 75), active_tree->ScrollableSize());
3131 EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
3134 // Fully hide the top controls.
3136 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
3137 ASSERT_EQ(gfx::Size(50, 100), inner_container->bounds());
3138 ASSERT_EQ(gfx::Size(50, 100), outer_container->bounds());
3139 EXPECT_EQ(gfx::SizeF(50, 100), active_tree->ScrollableSize());
3140 EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
3143 // Scrolling additionally shouldn't have any effect.
3145 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
3146 ASSERT_EQ(gfx::Size(50, 100), inner_container->bounds());
3147 ASSERT_EQ(gfx::Size(50, 100), outer_container->bounds());
3148 EXPECT_EQ(gfx::SizeF(50, 100), active_tree->ScrollableSize());
3149 EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
3152 host_impl_->top_controls_manager()->ScrollEnd();
3153 host_impl_->ScrollEnd();
3156 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
3157 SetupTopControlsAndScrollLayerWithVirtualViewport(
3158 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
3159 DrawFrame();
3161 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3162 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3164 // Make the test scroll delta a fractional amount, to verify that the
3165 // fixed container size delta is (1) non-zero, and (2) fractional, and
3166 // (3) matches the movement of the top controls.
3167 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
3168 host_impl_->top_controls_manager()->ScrollBegin();
3169 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3170 host_impl_->top_controls_manager()->ScrollEnd();
3172 LayerImpl* inner_viewport_scroll_layer =
3173 host_impl_->active_tree()->InnerViewportScrollLayer();
3174 DCHECK(inner_viewport_scroll_layer);
3175 host_impl_->ScrollEnd();
3176 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
3177 inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
3180 // In this test, the outer viewport is initially unscrollable. We test that a
3181 // scroll initiated on the inner viewport, causing the top controls to show and
3182 // thus making the outer viewport scrollable, still scrolls the outer viewport.
3183 TEST_F(LayerTreeHostImplTopControlsTest,
3184 TopControlsOuterViewportBecomesScrollable) {
3185 SetupTopControlsAndScrollLayerWithVirtualViewport(
3186 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
3187 DrawFrame();
3189 LayerImpl* inner_scroll =
3190 host_impl_->active_tree()->InnerViewportScrollLayer();
3191 LayerImpl* inner_container =
3192 host_impl_->active_tree()->InnerViewportContainerLayer();
3193 LayerImpl* outer_scroll =
3194 host_impl_->active_tree()->OuterViewportScrollLayer();
3195 LayerImpl* outer_container =
3196 host_impl_->active_tree()->OuterViewportContainerLayer();
3198 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
3199 outer_scroll->SetDrawsContent(true);
3200 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
3202 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3203 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3204 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
3206 // The entire scroll delta should have been used to hide the top controls.
3207 // The viewport layers should be resized back to their full sizes.
3208 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3209 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
3210 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
3211 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
3213 // The inner viewport should be scrollable by 50px * page_scale.
3214 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
3215 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
3216 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
3217 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
3219 host_impl_->ScrollEnd();
3221 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3222 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3223 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
3225 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
3227 // The entire scroll delta should have been used to show the top controls.
3228 // The outer viewport should be resized to accomodate and scrolled to the
3229 // bottom of the document to keep the viewport in place.
3230 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3231 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
3232 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
3233 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
3234 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
3236 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3237 // since it wasn't scrollable when the scroll began.
3238 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
3239 EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
3240 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
3242 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
3243 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
3244 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
3246 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
3247 host_impl_->ScrollEnd();
3249 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
3250 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
3253 // Test that the fixed position container delta is appropriately adjusted
3254 // by the top controls showing/hiding and page scale doesn't affect it.
3255 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
3256 SetupTopControlsAndScrollLayerWithVirtualViewport(
3257 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3258 DrawFrame();
3259 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3261 float page_scale = 1.5f;
3262 LayerImpl* outer_viewport_scroll_layer =
3263 host_impl_->active_tree()->OuterViewportScrollLayer();
3265 // Zoom in, since the fixed container is the outer viewport, the delta should
3266 // not be scaled.
3267 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
3269 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3270 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3272 // Scroll down, the top controls hiding should expand the viewport size so
3273 // the delta should be equal to the scroll distance.
3274 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
3275 host_impl_->top_controls_manager()->ScrollBegin();
3276 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3277 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
3278 host_impl_->top_controls_manager()->ContentTopOffset());
3279 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
3280 outer_viewport_scroll_layer->FixedContainerSizeDelta().y());
3281 host_impl_->ScrollEnd();
3283 // Scroll past the maximum extent. The delta shouldn't be greater than the
3284 // top controls height.
3285 host_impl_->top_controls_manager()->ScrollBegin();
3286 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3287 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3288 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3289 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3290 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
3291 outer_viewport_scroll_layer->FixedContainerSizeDelta());
3292 host_impl_->ScrollEnd();
3294 // Scroll in the direction to make the top controls show.
3295 host_impl_->top_controls_manager()->ScrollBegin();
3296 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
3297 EXPECT_EQ(top_controls_scroll_delta.y(),
3298 host_impl_->top_controls_manager()->ContentTopOffset());
3299 EXPECT_VECTOR_EQ(
3300 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
3301 outer_viewport_scroll_layer->FixedContainerSizeDelta());
3302 host_impl_->top_controls_manager()->ScrollEnd();
3305 // Test that if only the top controls are scrolled, we shouldn't request a
3306 // commit.
3307 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsDontTriggerCommit) {
3308 SetupTopControlsAndScrollLayerWithVirtualViewport(
3309 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3310 DrawFrame();
3312 // Show top controls
3313 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3315 // Scroll 25px to hide top controls
3316 gfx::Vector2dF scroll_delta(0.f, 25.f);
3317 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3318 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3319 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3320 EXPECT_FALSE(did_request_commit_);
3323 // Test that if a scrollable sublayer doesn't consume the scroll,
3324 // top controls should hide when scrolling down.
3325 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
3326 gfx::Size sub_content_size(100, 400);
3327 gfx::Size sub_content_layer_size(100, 300);
3328 SetupTopControlsAndScrollLayerWithVirtualViewport(
3329 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3330 DrawFrame();
3332 // Show top controls
3333 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3335 LayerImpl* outer_viewport_scroll_layer =
3336 host_impl_->active_tree()->OuterViewportScrollLayer();
3337 int id = outer_viewport_scroll_layer->id();
3339 scoped_ptr<LayerImpl> child =
3340 LayerImpl::Create(host_impl_->active_tree(), id + 2);
3341 scoped_ptr<LayerImpl> child_clip =
3342 LayerImpl::Create(host_impl_->active_tree(), id + 3);
3344 child_clip->SetBounds(sub_content_layer_size);
3345 child->SetScrollClipLayer(child_clip->id());
3346 child->SetBounds(sub_content_size);
3347 child->SetPosition(gfx::PointF());
3348 child->SetDrawsContent(true);
3349 child->SetIsContainerForFixedPositionLayers(true);
3351 // scroll child to limit
3352 child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
3353 child_clip->AddChild(child.Pass());
3354 outer_viewport_scroll_layer->AddChild(child_clip.Pass());
3356 // Scroll 25px to hide top controls
3357 gfx::Vector2dF scroll_delta(0.f, 25.f);
3358 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3359 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3360 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3361 host_impl_->ScrollEnd();
3363 // Top controls should be hidden
3364 EXPECT_EQ(scroll_delta.y(),
3365 top_controls_height_ -
3366 host_impl_->top_controls_manager()->ContentTopOffset());
3369 // Ensure setting the top controls position explicitly using the setters on the
3370 // TreeImpl correctly affects the top controls manager and viewport bounds.
3371 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
3372 CreateHostImpl(settings_, CreateOutputSurface());
3373 SetupTopControlsAndScrollLayerWithVirtualViewport(
3374 layer_size_, layer_size_, layer_size_);
3375 DrawFrame();
3377 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3378 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3379 30.f / top_controls_height_);
3380 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3381 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
3382 EXPECT_FLOAT_EQ(-20.f,
3383 host_impl_->top_controls_manager()->ControlsTopOffset());
3385 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3386 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3387 EXPECT_FLOAT_EQ(-50.f,
3388 host_impl_->top_controls_manager()->ControlsTopOffset());
3390 host_impl_->DidChangeTopControlsPosition();
3392 // Now that top controls have moved, expect the clip to resize.
3393 LayerImpl* inner_clip_ptr =
3394 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3395 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3398 // Test that the top_controls delta and sent delta are appropriately
3399 // applied on sync tree activation. The total top controls offset shouldn't
3400 // change after the activation.
3401 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
3402 CreateHostImpl(settings_, CreateOutputSurface());
3403 SetupTopControlsAndScrollLayerWithVirtualViewport(
3404 layer_size_, layer_size_, layer_size_);
3405 DrawFrame();
3407 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3408 20.f / top_controls_height_);
3409 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3410 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
3411 15.f / top_controls_height_);
3412 host_impl_->active_tree()
3413 ->top_controls_shown_ratio()
3414 ->PullDeltaForMainThread();
3415 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3416 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
3417 top_controls_height_);
3419 host_impl_->DidChangeTopControlsPosition();
3420 LayerImpl* inner_clip_ptr =
3421 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3422 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3423 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3425 host_impl_->ActivateSyncTree();
3427 inner_clip_ptr = host_impl_->InnerViewportScrollLayer()->parent()->parent();
3428 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3429 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3431 EXPECT_FLOAT_EQ(
3432 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
3433 top_controls_height_);
3434 EXPECT_FLOAT_EQ(
3435 15.f,
3436 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3437 top_controls_height_);
3440 // Test that changing the top controls layout height is correctly applied to
3441 // the inner viewport container bounds. That is, the top controls layout
3442 // height is the amount that the inner viewport container was shrunk outside
3443 // the compositor to accommodate the top controls.
3444 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
3445 CreateHostImpl(settings_, CreateOutputSurface());
3446 SetupTopControlsAndScrollLayerWithVirtualViewport(
3447 layer_size_, layer_size_, layer_size_);
3448 DrawFrame();
3450 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
3451 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
3453 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3454 1.f);
3455 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3456 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3458 host_impl_->DidChangeTopControlsPosition();
3459 LayerImpl* inner_clip_ptr =
3460 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3461 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3462 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3464 host_impl_->sync_tree()->root_layer()->SetBounds(
3465 gfx::Size(inner_clip_ptr->bounds().width(),
3466 inner_clip_ptr->bounds().height() - 50.f));
3468 host_impl_->ActivateSyncTree();
3470 inner_clip_ptr =
3471 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3472 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3474 // The total bounds should remain unchanged since the bounds delta should
3475 // account for the difference between the layout height and the current
3476 // top controls offset.
3477 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3478 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), inner_clip_ptr->bounds_delta());
3480 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
3481 host_impl_->DidChangeTopControlsPosition();
3483 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
3484 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
3485 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
3486 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), inner_clip_ptr->bounds_delta());
3487 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
3488 inner_clip_ptr->bounds());
3491 // Test that showing/hiding the top controls when the viewport is fully scrolled
3492 // doesn't incorrectly change the viewport offset due to clamping from changing
3493 // viewport bounds.
3494 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
3495 SetupTopControlsAndScrollLayerWithVirtualViewport(
3496 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3497 DrawFrame();
3499 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3501 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
3502 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
3504 // Scroll the viewports to max scroll offset.
3505 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3506 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3508 gfx::ScrollOffset viewport_offset =
3509 host_impl_->active_tree()->TotalScrollOffset();
3510 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
3512 // Hide the top controls by 25px.
3513 gfx::Vector2dF scroll_delta(0.f, 25.f);
3514 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3515 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3516 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3518 // scrolling down at the max extents no longer hides the top controls
3519 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3521 // forcefully hide the top controls by 25px
3522 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
3523 host_impl_->ScrollEnd();
3525 EXPECT_FLOAT_EQ(scroll_delta.y(),
3526 top_controls_height_ -
3527 host_impl_->top_controls_manager()->ContentTopOffset());
3529 inner_scroll->ClampScrollToMaxScrollOffset();
3530 outer_scroll->ClampScrollToMaxScrollOffset();
3532 // We should still be fully scrolled.
3533 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3534 host_impl_->active_tree()->TotalScrollOffset());
3536 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
3538 // Bring the top controls down by 25px.
3539 scroll_delta = gfx::Vector2dF(0.f, -25.f);
3540 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3541 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3542 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3543 host_impl_->ScrollEnd();
3545 // The viewport offset shouldn't have changed.
3546 EXPECT_EQ(viewport_offset,
3547 host_impl_->active_tree()->TotalScrollOffset());
3549 // Scroll the viewports to max scroll offset.
3550 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3551 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3552 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3553 host_impl_->active_tree()->TotalScrollOffset());
3556 // Test that the top controls coming in and out maintains the same aspect ratio
3557 // between the inner and outer viewports.
3558 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
3559 SetupTopControlsAndScrollLayerWithVirtualViewport(
3560 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3561 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 2.f);
3562 DrawFrame();
3564 EXPECT_FLOAT_EQ(top_controls_height_,
3565 host_impl_->top_controls_manager()->ContentTopOffset());
3567 gfx::Vector2dF scroll_delta(0.f, 25.f);
3568 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3569 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3570 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3571 host_impl_->ScrollEnd();
3573 EXPECT_FLOAT_EQ(scroll_delta.y(),
3574 top_controls_height_ -
3575 host_impl_->top_controls_manager()->ContentTopOffset());
3577 // Top controls were hidden by 25px so the inner viewport should have expanded
3578 // by that much.
3579 LayerImpl* outer_container =
3580 host_impl_->active_tree()->OuterViewportContainerLayer();
3581 LayerImpl* inner_container =
3582 host_impl_->active_tree()->InnerViewportContainerLayer();
3583 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
3585 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3586 float aspect_ratio = inner_container->BoundsForScrolling().width() /
3587 inner_container->BoundsForScrolling().height();
3588 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
3589 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
3590 EXPECT_EQ(expected,
3591 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
3594 // Test that scrolling the outer viewport affects the top controls.
3595 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
3596 SetupTopControlsAndScrollLayerWithVirtualViewport(
3597 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3598 DrawFrame();
3600 EXPECT_EQ(top_controls_height_,
3601 host_impl_->top_controls_manager()->ContentTopOffset());
3603 // Send a gesture scroll that will scroll the outer viewport, make sure the
3604 // top controls get scrolled.
3605 gfx::Vector2dF scroll_delta(0.f, 15.f);
3606 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3607 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3608 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3609 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3610 host_impl_->CurrentlyScrollingLayer());
3611 host_impl_->ScrollEnd();
3613 EXPECT_FLOAT_EQ(scroll_delta.y(),
3614 top_controls_height_ -
3615 host_impl_->top_controls_manager()->ContentTopOffset());
3617 scroll_delta = gfx::Vector2dF(0.f, 50.f);
3618 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3619 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3620 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3622 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
3623 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3624 host_impl_->CurrentlyScrollingLayer());
3626 host_impl_->ScrollEnd();
3628 // Position the viewports such that the inner viewport will be scrolled.
3629 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
3630 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3631 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
3633 scroll_delta = gfx::Vector2dF(0.f, -65.f);
3634 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3635 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3636 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3638 EXPECT_EQ(top_controls_height_,
3639 host_impl_->top_controls_manager()->ContentTopOffset());
3640 EXPECT_FLOAT_EQ(
3641 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
3642 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
3644 host_impl_->ScrollEnd();
3647 TEST_F(LayerTreeHostImplTopControlsTest,
3648 ScrollNonScrollableRootWithTopControls) {
3649 CreateHostImpl(settings_, CreateOutputSurface());
3650 SetupTopControlsAndScrollLayerWithVirtualViewport(
3651 layer_size_, layer_size_, layer_size_);
3652 DrawFrame();
3654 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3655 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3657 host_impl_->top_controls_manager()->ScrollBegin();
3658 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
3659 host_impl_->top_controls_manager()->ScrollEnd();
3660 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3661 // Now that top controls have moved, expect the clip to resize.
3662 LayerImpl* inner_clip_ptr =
3663 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3664 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3666 host_impl_->ScrollEnd();
3668 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3669 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3671 float scroll_increment_y = -25.f;
3672 host_impl_->top_controls_manager()->ScrollBegin();
3673 host_impl_->top_controls_manager()->ScrollBy(
3674 gfx::Vector2dF(0.f, scroll_increment_y));
3675 EXPECT_FLOAT_EQ(-scroll_increment_y,
3676 host_impl_->top_controls_manager()->ContentTopOffset());
3677 // Now that top controls have moved, expect the clip to resize.
3678 EXPECT_EQ(gfx::Size(viewport_size_.width(),
3679 viewport_size_.height() + scroll_increment_y),
3680 inner_clip_ptr->bounds());
3682 host_impl_->top_controls_manager()->ScrollBy(
3683 gfx::Vector2dF(0.f, scroll_increment_y));
3684 host_impl_->top_controls_manager()->ScrollEnd();
3685 EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
3686 host_impl_->top_controls_manager()->ContentTopOffset());
3687 // Now that top controls have moved, expect the clip to resize.
3688 EXPECT_EQ(clip_size_, inner_clip_ptr->bounds());
3690 host_impl_->ScrollEnd();
3692 // Verify the layer is once-again non-scrollable.
3693 EXPECT_EQ(
3694 gfx::ScrollOffset(),
3695 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3697 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3698 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3701 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
3702 // Test the configuration where a non-composited root layer is embedded in a
3703 // scrollable outer layer.
3704 gfx::Size surface_size(10, 10);
3705 gfx::Size contents_size(20, 20);
3707 scoped_ptr<LayerImpl> content_layer =
3708 LayerImpl::Create(host_impl_->active_tree(), 1);
3709 content_layer->SetDrawsContent(true);
3710 content_layer->SetPosition(gfx::PointF());
3711 content_layer->SetBounds(contents_size);
3713 scoped_ptr<LayerImpl> scroll_clip_layer =
3714 LayerImpl::Create(host_impl_->active_tree(), 3);
3715 scroll_clip_layer->SetBounds(surface_size);
3717 scoped_ptr<LayerImpl> scroll_layer =
3718 LayerImpl::Create(host_impl_->active_tree(), 2);
3719 scroll_layer->SetScrollClipLayer(3);
3720 scroll_layer->SetBounds(contents_size);
3721 scroll_layer->SetPosition(gfx::PointF());
3722 scroll_layer->AddChild(content_layer.Pass());
3723 scroll_clip_layer->AddChild(scroll_layer.Pass());
3725 scroll_clip_layer->SetHasRenderSurface(true);
3726 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
3727 host_impl_->SetViewportSize(surface_size);
3728 DrawFrame();
3730 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3731 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3732 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3733 host_impl_->ScrollEnd();
3734 EXPECT_TRUE(did_request_redraw_);
3735 EXPECT_TRUE(did_request_commit_);
3738 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
3739 gfx::Size surface_size(10, 10);
3740 gfx::Size contents_size(20, 20);
3741 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3742 root->SetBounds(surface_size);
3743 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
3744 root->SetHasRenderSurface(true);
3745 host_impl_->active_tree()->SetRootLayer(root.Pass());
3746 host_impl_->SetViewportSize(surface_size);
3747 DrawFrame();
3749 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3750 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3751 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3752 host_impl_->ScrollEnd();
3753 EXPECT_TRUE(did_request_redraw_);
3754 EXPECT_TRUE(did_request_commit_);
3757 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
3758 gfx::Size surface_size(10, 10);
3759 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3760 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
3761 root->SetHasRenderSurface(true);
3762 host_impl_->active_tree()->SetRootLayer(root.Pass());
3763 host_impl_->SetViewportSize(surface_size);
3764 DrawFrame();
3766 // Scroll event is ignored because the input coordinate is outside the layer
3767 // boundaries.
3768 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3769 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
3770 EXPECT_FALSE(did_request_redraw_);
3771 EXPECT_FALSE(did_request_commit_);
3774 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
3775 gfx::Size surface_size(10, 10);
3776 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3777 root->SetHasRenderSurface(true);
3778 scoped_ptr<LayerImpl> child =
3779 CreateScrollableLayer(2, surface_size, root.get());
3780 host_impl_->SetViewportSize(surface_size);
3782 gfx::Transform matrix;
3783 matrix.RotateAboutXAxis(180.0);
3784 child->SetTransform(matrix);
3785 child->SetDoubleSided(false);
3787 root->AddChild(child.Pass());
3788 host_impl_->active_tree()->SetRootLayer(root.Pass());
3789 DrawFrame();
3791 // Scroll event is ignored because the scrollable layer is not facing the
3792 // viewer and there is nothing scrollable behind it.
3793 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3794 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3795 EXPECT_FALSE(did_request_redraw_);
3796 EXPECT_FALSE(did_request_commit_);
3799 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
3800 gfx::Size surface_size(10, 10);
3801 scoped_ptr<LayerImpl> clip_layer =
3802 LayerImpl::Create(host_impl_->active_tree(), 3);
3803 scoped_ptr<LayerImpl> content_layer =
3804 CreateScrollableLayer(1, surface_size, clip_layer.get());
3805 content_layer->SetShouldScrollOnMainThread(true);
3806 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
3808 // Note: we can use the same clip layer for both since both calls to
3809 // CreateScrollableLayer() use the same surface size.
3810 scoped_ptr<LayerImpl> scroll_layer =
3811 CreateScrollableLayer(2, surface_size, clip_layer.get());
3812 scroll_layer->AddChild(content_layer.Pass());
3813 clip_layer->AddChild(scroll_layer.Pass());
3814 clip_layer->SetHasRenderSurface(true);
3816 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
3817 host_impl_->SetViewportSize(surface_size);
3818 DrawFrame();
3820 // Scrolling fails because the content layer is asking to be scrolled on the
3821 // main thread.
3822 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
3823 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3826 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
3827 gfx::Size viewport_size(10, 10);
3828 float page_scale = 2.f;
3830 SetupScrollAndContentsLayers(viewport_size);
3832 // Setup the layers so that the outer viewport is scrollable.
3833 host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3834 viewport_size);
3835 host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
3836 gfx::Size(20, 20));
3837 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3838 DrawFrame();
3840 LayerImpl* root_scroll =
3841 host_impl_->active_tree()->OuterViewportScrollLayer();
3842 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3844 gfx::Vector2d scroll_delta(0, 10);
3845 gfx::Vector2d expected_scroll_delta = scroll_delta;
3846 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3847 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3848 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3849 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3850 host_impl_->ScrollEnd();
3852 // Set new page scale from main thread.
3853 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
3855 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3856 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
3857 expected_scroll_delta));
3859 // The scroll range should also have been updated.
3860 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3862 // The page scale delta remains constant because the impl thread did not
3863 // scale.
3864 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3867 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3868 gfx::Size viewport_size(10, 10);
3869 float page_scale = 2.f;
3871 SetupScrollAndContentsLayers(viewport_size);
3873 // Setup the layers so that the outer viewport is scrollable.
3874 host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3875 viewport_size);
3876 host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
3877 gfx::Size(20, 20));
3878 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3879 DrawFrame();
3881 LayerImpl* root_scroll =
3882 host_impl_->active_tree()->OuterViewportScrollLayer();
3883 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3885 gfx::Vector2d scroll_delta(0, 10);
3886 gfx::Vector2d expected_scroll_delta = scroll_delta;
3887 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3888 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3889 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3890 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3891 host_impl_->ScrollEnd();
3893 // Set new page scale on impl thread by pinching.
3894 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3895 host_impl_->PinchGestureBegin();
3896 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3897 host_impl_->PinchGestureEnd();
3898 host_impl_->ScrollEnd();
3899 DrawOneFrame();
3901 // The scroll delta is not scaled because the main thread did not scale.
3902 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3903 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
3904 expected_scroll_delta));
3906 // The scroll range should also have been updated.
3907 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3909 // The page scale delta should match the new scale on the impl side.
3910 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3913 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3914 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3915 gfx::Size surface_size(10, 10);
3916 float default_page_scale = 1.f;
3917 gfx::Transform default_page_scale_matrix;
3918 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3920 float new_page_scale = 2.f;
3921 gfx::Transform new_page_scale_matrix;
3922 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3924 // Create a normal scrollable root layer and another scrollable child layer.
3925 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3926 LayerImpl* root = host_impl_->active_tree()->root_layer();
3927 LayerImpl* child = scroll->children()[0];
3929 scoped_ptr<LayerImpl> scrollable_child_clip =
3930 LayerImpl::Create(host_impl_->active_tree(), 6);
3931 scoped_ptr<LayerImpl> scrollable_child =
3932 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3933 scrollable_child_clip->AddChild(scrollable_child.Pass());
3934 child->AddChild(scrollable_child_clip.Pass());
3935 LayerImpl* grand_child = child->children()[0];
3937 // Set new page scale on impl thread by pinching.
3938 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3939 host_impl_->PinchGestureBegin();
3940 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3941 host_impl_->PinchGestureEnd();
3942 host_impl_->ScrollEnd();
3943 DrawOneFrame();
3945 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3946 // the page scale delta on the root layer is applied hierarchically.
3947 LayerTreeHostImpl::FrameData frame;
3948 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3949 host_impl_->DrawLayers(&frame);
3950 host_impl_->DidDrawAllLayers(frame);
3952 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3953 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3954 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3955 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3956 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3957 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3958 EXPECT_EQ(new_page_scale,
3959 grand_child->draw_transform().matrix().getDouble(0, 0));
3960 EXPECT_EQ(new_page_scale,
3961 grand_child->draw_transform().matrix().getDouble(1, 1));
3964 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3965 gfx::Size surface_size(30, 30);
3966 SetupScrollAndContentsLayers(surface_size);
3968 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
3970 // Make the outer scroll layer scrollable.
3971 outer_scroll->SetBounds(gfx::Size(50, 50));
3973 DrawFrame();
3975 gfx::Vector2d scroll_delta(0, 10);
3976 gfx::Vector2d expected_scroll_delta(scroll_delta);
3977 gfx::ScrollOffset expected_max_scroll(outer_scroll->MaxScrollOffset());
3978 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3979 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3980 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3981 host_impl_->ScrollEnd();
3983 float page_scale = 2.f;
3984 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
3985 page_scale);
3987 DrawOneFrame();
3989 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3990 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), outer_scroll->id(),
3991 expected_scroll_delta));
3993 // The scroll range should not have changed.
3994 EXPECT_EQ(outer_scroll->MaxScrollOffset(), expected_max_scroll);
3996 // The page scale delta remains constant because the impl thread did not
3997 // scale.
3998 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
4001 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
4002 // Scroll a child layer beyond its maximum scroll range and make sure the
4003 // parent layer is scrolled on the axis on which the child was unable to
4004 // scroll.
4005 gfx::Size surface_size(10, 10);
4006 gfx::Size content_size(20, 20);
4007 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
4008 root->SetBounds(surface_size);
4009 root->SetHasRenderSurface(true);
4010 scoped_ptr<LayerImpl> grand_child =
4011 CreateScrollableLayer(3, content_size, root.get());
4013 scoped_ptr<LayerImpl> child =
4014 CreateScrollableLayer(2, content_size, root.get());
4015 LayerImpl* grand_child_layer = grand_child.get();
4016 child->AddChild(grand_child.Pass());
4018 LayerImpl* child_layer = child.get();
4019 root->AddChild(child.Pass());
4020 host_impl_->active_tree()->SetRootLayer(root.Pass());
4021 host_impl_->active_tree()->DidBecomeActive();
4022 host_impl_->SetViewportSize(surface_size);
4023 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
4024 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
4026 DrawFrame();
4028 gfx::Vector2d scroll_delta(-8, -7);
4029 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4030 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4031 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4032 host_impl_->ScrollEnd();
4034 scoped_ptr<ScrollAndScaleSet> scroll_info =
4035 host_impl_->ProcessScrollDeltas();
4037 // The grand child should have scrolled up to its limit.
4038 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4039 LayerImpl* grand_child = child->children()[0];
4040 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4041 gfx::Vector2d(0, -5)));
4043 // The child should have only scrolled on the other axis.
4044 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
4045 gfx::Vector2d(-3, 0)));
4049 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
4050 // Scroll a child layer beyond its maximum scroll range and make sure the
4051 // the scroll doesn't bubble up to the parent layer.
4052 gfx::Size surface_size(20, 20);
4053 gfx::Size viewport_size(10, 10);
4054 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
4055 root->SetHasRenderSurface(true);
4056 scoped_ptr<LayerImpl> root_scrolling =
4057 CreateScrollableLayer(2, surface_size, root.get());
4058 root_scrolling->SetIsContainerForFixedPositionLayers(true);
4060 scoped_ptr<LayerImpl> grand_child =
4061 CreateScrollableLayer(4, surface_size, root.get());
4063 scoped_ptr<LayerImpl> child =
4064 CreateScrollableLayer(3, surface_size, root.get());
4065 LayerImpl* grand_child_layer = grand_child.get();
4066 child->AddChild(grand_child.Pass());
4068 LayerImpl* child_layer = child.get();
4069 root_scrolling->AddChild(child.Pass());
4070 root->AddChild(root_scrolling.Pass());
4071 EXPECT_EQ(viewport_size, root->bounds());
4072 host_impl_->active_tree()->SetRootLayer(root.Pass());
4073 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
4074 Layer::INVALID_ID);
4075 host_impl_->active_tree()->DidBecomeActive();
4076 host_impl_->SetViewportSize(viewport_size);
4078 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4079 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4081 DrawFrame();
4083 gfx::Vector2d scroll_delta(0, -10);
4084 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4085 host_impl_->ScrollBegin(gfx::Point(),
4086 InputHandler::NON_BUBBLING_GESTURE));
4087 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4088 host_impl_->ScrollEnd();
4090 scoped_ptr<ScrollAndScaleSet> scroll_info =
4091 host_impl_->ProcessScrollDeltas();
4093 // The grand child should have scrolled up to its limit.
4094 LayerImpl* child =
4095 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
4096 LayerImpl* grand_child = child->children()[0];
4097 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4098 gfx::Vector2d(0, -2)));
4100 // The child should not have scrolled.
4101 ExpectNone(*scroll_info.get(), child->id());
4103 // The next time we scroll we should only scroll the parent.
4104 scroll_delta = gfx::Vector2d(0, -3);
4105 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4106 host_impl_->ScrollBegin(gfx::Point(5, 5),
4107 InputHandler::NON_BUBBLING_GESTURE));
4108 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
4109 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4110 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
4111 host_impl_->ScrollEnd();
4113 scroll_info = host_impl_->ProcessScrollDeltas();
4115 // The child should have scrolled up to its limit.
4116 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
4117 gfx::Vector2d(0, -3)));
4119 // The grand child should not have scrolled.
4120 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4121 gfx::Vector2d(0, -2)));
4123 // After scrolling the parent, another scroll on the opposite direction
4124 // should still scroll the child.
4125 scroll_delta = gfx::Vector2d(0, 7);
4126 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4127 host_impl_->ScrollBegin(gfx::Point(5, 5),
4128 InputHandler::NON_BUBBLING_GESTURE));
4129 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
4130 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4131 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
4132 host_impl_->ScrollEnd();
4134 scroll_info = host_impl_->ProcessScrollDeltas();
4136 // The grand child should have scrolled.
4137 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4138 gfx::Vector2d(0, 5)));
4140 // The child should not have scrolled.
4141 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
4142 gfx::Vector2d(0, -3)));
4144 // Scrolling should be adjusted from viewport space.
4145 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
4146 host_impl_->SetPageScaleOnActiveTree(2.f);
4148 scroll_delta = gfx::Vector2d(0, -2);
4149 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4150 host_impl_->ScrollBegin(gfx::Point(1, 1),
4151 InputHandler::NON_BUBBLING_GESTURE));
4152 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
4153 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4154 host_impl_->ScrollEnd();
4156 scroll_info = host_impl_->ProcessScrollDeltas();
4158 // Should have scrolled by half the amount in layer space (5 - 2/2)
4159 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4160 gfx::Vector2d(0, 4)));
4163 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
4164 // When we try to scroll a non-scrollable child layer, the scroll delta
4165 // should be applied to one of its ancestors if possible.
4166 gfx::Size surface_size(10, 10);
4167 gfx::Size content_size(20, 20);
4168 scoped_ptr<LayerImpl> root_clip =
4169 LayerImpl::Create(host_impl_->active_tree(), 3);
4170 root_clip->SetHasRenderSurface(true);
4171 scoped_ptr<LayerImpl> root =
4172 CreateScrollableLayer(1, content_size, root_clip.get());
4173 // Make 'root' the clip layer for child: since they have the same sizes the
4174 // child will have zero max_scroll_offset and scrolls will bubble.
4175 scoped_ptr<LayerImpl> child =
4176 CreateScrollableLayer(2, content_size, root.get());
4177 child->SetIsContainerForFixedPositionLayers(true);
4178 root->SetBounds(content_size);
4180 int root_scroll_id = root->id();
4181 root->AddChild(child.Pass());
4182 root_clip->AddChild(root.Pass());
4184 host_impl_->SetViewportSize(surface_size);
4185 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4186 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
4187 Layer::INVALID_ID);
4188 host_impl_->active_tree()->DidBecomeActive();
4189 DrawFrame();
4191 gfx::Vector2d scroll_delta(0, 4);
4192 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4193 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4194 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4195 host_impl_->ScrollEnd();
4197 scoped_ptr<ScrollAndScaleSet> scroll_info =
4198 host_impl_->ProcessScrollDeltas();
4200 // Only the root scroll should have scrolled.
4201 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
4202 EXPECT_TRUE(
4203 ScrollInfoContains(*scroll_info.get(), root_scroll_id, scroll_delta));
4207 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
4208 gfx::Size surface_size(10, 10);
4209 scoped_ptr<LayerImpl> root_clip =
4210 LayerImpl::Create(host_impl_->active_tree(), 1);
4211 scoped_ptr<LayerImpl> root_scroll =
4212 CreateScrollableLayer(2, surface_size, root_clip.get());
4213 root_scroll->SetIsContainerForFixedPositionLayers(true);
4214 root_clip->SetHasRenderSurface(true);
4215 root_clip->AddChild(root_scroll.Pass());
4216 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4217 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
4218 Layer::INVALID_ID);
4219 host_impl_->active_tree()->DidBecomeActive();
4220 host_impl_->SetViewportSize(surface_size);
4222 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4223 // synchronization.
4224 DrawFrame();
4225 host_impl_->active_tree()->DetachLayerTree();
4226 scoped_ptr<LayerImpl> root_clip2 =
4227 LayerImpl::Create(host_impl_->active_tree(), 3);
4228 scoped_ptr<LayerImpl> root_scroll2 =
4229 CreateScrollableLayer(4, surface_size, root_clip2.get());
4230 root_scroll2->SetIsContainerForFixedPositionLayers(true);
4231 root_clip2->AddChild(root_scroll2.Pass());
4232 root_clip2->SetHasRenderSurface(true);
4233 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
4234 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
4235 Layer::INVALID_ID);
4236 host_impl_->active_tree()->DidBecomeActive();
4238 // Scrolling should still work even though we did not draw yet.
4239 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4240 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4243 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
4244 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4246 // Rotate the root layer 90 degrees counter-clockwise about its center.
4247 gfx::Transform rotate_transform;
4248 rotate_transform.Rotate(-90.0);
4249 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
4251 gfx::Size surface_size(50, 50);
4252 host_impl_->SetViewportSize(surface_size);
4253 DrawFrame();
4255 // Scroll to the right in screen coordinates with a gesture.
4256 gfx::Vector2d gesture_scroll_delta(10, 0);
4257 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4258 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4259 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4260 host_impl_->ScrollEnd();
4262 // The layer should have scrolled down in its local coordinates.
4263 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
4264 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4265 gfx::Vector2d(0, gesture_scroll_delta.x())));
4267 // Reset and scroll down with the wheel.
4268 scroll_layer->SetScrollDelta(gfx::Vector2dF());
4269 gfx::Vector2d wheel_scroll_delta(0, 10);
4270 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4271 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4272 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
4273 host_impl_->ScrollEnd();
4275 // The layer should have scrolled down in its local coordinates.
4276 scroll_info = host_impl_->ProcessScrollDeltas();
4277 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4278 wheel_scroll_delta));
4281 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
4282 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4283 int child_clip_layer_id = 6;
4284 int child_layer_id = 7;
4285 float child_layer_angle = -20.f;
4287 // Create a child layer that is rotated to a non-axis-aligned angle.
4288 scoped_ptr<LayerImpl> clip_layer =
4289 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
4290 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
4291 child_layer_id, scroll_layer->bounds(), clip_layer.get());
4292 gfx::Transform rotate_transform;
4293 rotate_transform.Translate(-50.0, -50.0);
4294 rotate_transform.Rotate(child_layer_angle);
4295 rotate_transform.Translate(50.0, 50.0);
4296 clip_layer->SetTransform(rotate_transform);
4298 // Only allow vertical scrolling.
4299 clip_layer->SetBounds(
4300 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
4301 // The rotation depends on the layer's transform origin, and the child layer
4302 // is a different size than the clip, so make sure the clip layer's origin
4303 // lines up over the child.
4304 clip_layer->SetTransformOrigin(gfx::Point3F(
4305 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
4306 LayerImpl* child_ptr = child.get();
4307 clip_layer->AddChild(child.Pass());
4308 scroll_layer->AddChild(clip_layer.Pass());
4310 gfx::Size surface_size(50, 50);
4311 host_impl_->SetViewportSize(surface_size);
4312 DrawFrame();
4314 // Scroll down in screen coordinates with a gesture.
4315 gfx::Vector2d gesture_scroll_delta(0, 10);
4316 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4317 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4318 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4319 host_impl_->ScrollEnd();
4321 // The child layer should have scrolled down in its local coordinates an
4322 // amount proportional to the angle between it and the input scroll delta.
4323 gfx::Vector2d expected_scroll_delta(
4324 0, gesture_scroll_delta.y() *
4325 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
4326 scoped_ptr<ScrollAndScaleSet> scroll_info =
4327 host_impl_->ProcessScrollDeltas();
4328 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4329 expected_scroll_delta));
4331 // The root scroll layer should not have scrolled, because the input delta
4332 // was close to the layer's axis of movement.
4333 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4336 // Now reset and scroll the same amount horizontally.
4337 child_ptr->SetScrollDelta(gfx::Vector2dF());
4338 gfx::Vector2d gesture_scroll_delta(10, 0);
4339 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4340 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4341 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4342 host_impl_->ScrollEnd();
4344 // The child layer should have scrolled down in its local coordinates an
4345 // amount proportional to the angle between it and the input scroll delta.
4346 gfx::Vector2d expected_scroll_delta(
4347 0, -gesture_scroll_delta.x() *
4348 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
4349 scoped_ptr<ScrollAndScaleSet> scroll_info =
4350 host_impl_->ProcessScrollDeltas();
4351 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4352 expected_scroll_delta));
4354 // The root scroll layer should have scrolled more, since the input scroll
4355 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4356 gfx::Vector2d expected_root_scroll_delta(
4357 gesture_scroll_delta.x() *
4358 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
4360 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4361 expected_root_scroll_delta));
4365 TEST_F(LayerTreeHostImplTest, ScrollPerspectiveTransformedLayer) {
4366 // When scrolling an element with perspective, the distance scrolled
4367 // depends on the point at which the scroll begins.
4368 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4369 int child_clip_layer_id = 6;
4370 int child_layer_id = 7;
4372 // Create a child layer that is rotated on its x axis, with perspective.
4373 scoped_ptr<LayerImpl> clip_layer =
4374 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
4375 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
4376 child_layer_id, scroll_layer->bounds(), clip_layer.get());
4377 LayerImpl* child_ptr = child.get();
4378 gfx::Transform perspective_transform;
4379 perspective_transform.Translate(-50.0, -50.0);
4380 perspective_transform.ApplyPerspectiveDepth(20);
4381 perspective_transform.RotateAboutXAxis(45);
4382 perspective_transform.Translate(50.0, 50.0);
4383 clip_layer->SetTransform(perspective_transform);
4385 clip_layer->SetBounds(gfx::Size(child_ptr->bounds().width() / 2,
4386 child_ptr->bounds().height() / 2));
4387 // The transform depends on the layer's transform origin, and the child layer
4388 // is a different size than the clip, so make sure the clip layer's origin
4389 // lines up over the child.
4390 clip_layer->SetTransformOrigin(gfx::Point3F(
4391 clip_layer->bounds().width(), clip_layer->bounds().height(), 0.f));
4392 clip_layer->AddChild(child.Pass());
4393 scroll_layer->AddChild(clip_layer.Pass());
4395 gfx::Size surface_size(50, 50);
4396 host_impl_->SetViewportSize(surface_size);
4398 scoped_ptr<ScrollAndScaleSet> scroll_info;
4400 gfx::Vector2d gesture_scroll_deltas[4];
4401 gesture_scroll_deltas[0] = gfx::Vector2d(4, 10);
4402 gesture_scroll_deltas[1] = gfx::Vector2d(4, 10);
4403 gesture_scroll_deltas[2] = gfx::Vector2d(10, 0);
4404 gesture_scroll_deltas[3] = gfx::Vector2d(10, 0);
4406 gfx::Vector2d expected_scroll_deltas[4];
4407 // Perspective affects the vertical delta by a different
4408 // amount depending on the vertical position of the |viewport_point|.
4409 expected_scroll_deltas[0] = gfx::Vector2d(2, 8);
4410 expected_scroll_deltas[1] = gfx::Vector2d(1, 4);
4411 // Deltas which start with the same vertical position of the
4412 // |viewport_point| are subject to identical perspective effects.
4413 expected_scroll_deltas[2] = gfx::Vector2d(4, 0);
4414 expected_scroll_deltas[3] = gfx::Vector2d(4, 0);
4416 gfx::Point viewport_point(1, 1);
4418 // Scroll in screen coordinates with a gesture. Each scroll starts
4419 // where the previous scroll ended, but the scroll position is reset
4420 // for each scroll.
4421 for (int i = 0; i < 4; ++i) {
4422 child_ptr->SetScrollDelta(gfx::Vector2dF());
4423 DrawFrame();
4424 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4425 host_impl_->ScrollBegin(viewport_point, InputHandler::GESTURE));
4426 host_impl_->ScrollBy(viewport_point, gesture_scroll_deltas[i]);
4427 viewport_point += gesture_scroll_deltas[i];
4428 host_impl_->ScrollEnd();
4430 scroll_info = host_impl_->ProcessScrollDeltas();
4431 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4432 expected_scroll_deltas[i]));
4434 // The root scroll layer should not have scrolled, because the input delta
4435 // was close to the layer's axis of movement.
4436 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4440 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
4441 LayerImpl* scroll_layer =
4442 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4444 // Scale the layer to twice its normal size.
4445 int scale = 2;
4446 gfx::Transform scale_transform;
4447 scale_transform.Scale(scale, scale);
4448 scroll_layer->SetTransform(scale_transform);
4450 gfx::Size surface_size(50, 50);
4451 host_impl_->SetViewportSize(surface_size);
4452 DrawFrame();
4454 // Scroll down in screen coordinates with a gesture.
4455 gfx::Vector2d scroll_delta(0, 10);
4456 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4457 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4458 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4459 host_impl_->ScrollEnd();
4461 // The layer should have scrolled down in its local coordinates, but half the
4462 // amount.
4463 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
4464 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4465 gfx::Vector2d(0, scroll_delta.y() / scale)));
4467 // Reset and scroll down with the wheel.
4468 scroll_layer->SetScrollDelta(gfx::Vector2dF());
4469 gfx::Vector2d wheel_scroll_delta(0, 10);
4470 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4471 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4472 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
4473 host_impl_->ScrollEnd();
4475 // It should apply the scale factor to the scroll delta for the wheel event.
4476 scroll_info = host_impl_->ProcessScrollDeltas();
4477 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4478 wheel_scroll_delta));
4481 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
4482 int width = 332;
4483 int height = 20;
4484 int scale = 3;
4485 SetupScrollAndContentsLayers(gfx::Size(width, height));
4486 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
4487 gfx::Size(width * scale - 1, height * scale));
4488 host_impl_->SetDeviceScaleFactor(scale);
4489 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4491 LayerImpl* inner_viewport_scroll_layer =
4492 host_impl_->active_tree()->InnerViewportScrollLayer();
4493 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4494 inner_viewport_scroll_layer->MaxScrollOffset());
4497 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
4498 public:
4499 TestScrollOffsetDelegate()
4500 : page_scale_factor_(0.f),
4501 min_page_scale_factor_(-1.f),
4502 max_page_scale_factor_(-1.f) {}
4504 ~TestScrollOffsetDelegate() override {}
4506 gfx::ScrollOffset GetTotalScrollOffset() override {
4507 return getter_return_value_;
4510 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
4511 const gfx::ScrollOffset& max_scroll_offset,
4512 const gfx::SizeF& scrollable_size,
4513 float page_scale_factor,
4514 float min_page_scale_factor,
4515 float max_page_scale_factor) override {
4516 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
4517 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
4518 last_set_scroll_offset_ = total_scroll_offset;
4519 max_scroll_offset_ = max_scroll_offset;
4520 scrollable_size_ = scrollable_size;
4521 page_scale_factor_ = page_scale_factor;
4522 min_page_scale_factor_ = min_page_scale_factor;
4523 max_page_scale_factor_ = max_page_scale_factor;
4525 set_getter_return_value(last_set_scroll_offset_);
4528 gfx::ScrollOffset last_set_scroll_offset() {
4529 return last_set_scroll_offset_;
4532 void set_getter_return_value(const gfx::ScrollOffset& value) {
4533 getter_return_value_ = value;
4536 gfx::ScrollOffset max_scroll_offset() const {
4537 return max_scroll_offset_;
4540 gfx::SizeF scrollable_size() const {
4541 return scrollable_size_;
4544 float page_scale_factor() const {
4545 return page_scale_factor_;
4548 float min_page_scale_factor() const {
4549 return min_page_scale_factor_;
4552 float max_page_scale_factor() const {
4553 return max_page_scale_factor_;
4556 private:
4557 gfx::ScrollOffset last_set_scroll_offset_;
4558 gfx::ScrollOffset getter_return_value_;
4559 gfx::ScrollOffset max_scroll_offset_;
4560 gfx::SizeF scrollable_size_;
4561 float page_scale_factor_;
4562 float min_page_scale_factor_;
4563 float max_page_scale_factor_;
4566 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
4567 TestScrollOffsetDelegate scroll_delegate;
4568 host_impl_->SetViewportSize(gfx::Size(10, 20));
4569 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4570 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4571 clip_layer->SetBounds(gfx::Size(10, 20));
4573 // Setting the delegate results in the current scroll offset being set.
4574 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
4575 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4576 scroll_layer->SetScrollDelta(initial_scroll_delta);
4577 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4578 EXPECT_EQ(initial_scroll_delta.ToString(),
4579 scroll_delegate.last_set_scroll_offset().ToString());
4581 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4582 // page_scale_factor and {min|max}_page_scale_factor being set.
4583 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
4584 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
4585 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4586 EXPECT_EQ(1.f, scroll_delegate.min_page_scale_factor());
4587 EXPECT_EQ(1.f, scroll_delegate.max_page_scale_factor());
4589 // Updating page scale immediately updates the delegate.
4590 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
4591 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
4592 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4593 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4594 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
4595 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
4596 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4597 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4598 host_impl_->SetPageScaleOnActiveTree(2.f);
4599 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4600 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4601 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4602 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4604 // The pinch gesture doesn't put the delegate into a state where the scroll
4605 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4606 // delegate).
4607 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
4608 host_impl_->PinchGestureBegin();
4609 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
4610 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
4611 host_impl_->PinchGestureEnd();
4612 host_impl_->ScrollEnd();
4614 // Scrolling should be relative to the offset as given by the delegate.
4615 gfx::Vector2dF scroll_delta(0.f, 10.f);
4616 gfx::ScrollOffset current_offset(7.f, 8.f);
4618 scroll_delegate.set_getter_return_value(current_offset);
4619 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4620 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4621 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
4623 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4624 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
4625 scroll_delegate.last_set_scroll_offset());
4627 current_offset = gfx::ScrollOffset(42.f, 41.f);
4628 scroll_delegate.set_getter_return_value(current_offset);
4629 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
4630 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4631 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
4632 scroll_delegate.last_set_scroll_offset());
4633 host_impl_->ScrollEnd();
4634 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
4635 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(gfx::ScrollOffset());
4637 // Forces a full tree synchronization and ensures that the scroll delegate
4638 // sees the correct size of the new tree.
4639 gfx::Size new_size(42, 24);
4640 host_impl_->CreatePendingTree();
4641 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
4642 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
4643 host_impl_->ActivateSyncTree();
4644 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
4646 // Un-setting the delegate should propagate the delegate's current offset to
4647 // the root scrollable layer.
4648 current_offset = gfx::ScrollOffset(13.f, 12.f);
4649 scroll_delegate.set_getter_return_value(current_offset);
4650 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
4651 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4653 EXPECT_EQ(current_offset.ToString(),
4654 scroll_layer->CurrentScrollOffset().ToString());
4657 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
4658 const gfx::Transform target_space_transform =
4659 layer->draw_properties().target_space_transform;
4660 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
4661 gfx::Point translated_point;
4662 target_space_transform.TransformPoint(&translated_point);
4663 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
4664 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
4667 TEST_F(LayerTreeHostImplTest,
4668 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
4669 TestScrollOffsetDelegate scroll_delegate;
4670 host_impl_->SetViewportSize(gfx::Size(10, 20));
4671 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4672 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4673 clip_layer->SetBounds(gfx::Size(10, 20));
4674 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4676 // Draw first frame to clear any pending draws and check scroll.
4677 DrawFrame();
4678 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
4679 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
4681 // Set external scroll delta on delegate and notify LayerTreeHost.
4682 gfx::ScrollOffset scroll_offset(10.f, 10.f);
4683 scroll_delegate.set_getter_return_value(scroll_offset);
4684 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(scroll_offset);
4686 // Check scroll delta reflected in layer.
4687 LayerTreeHostImpl::FrameData frame;
4688 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4689 host_impl_->DrawLayers(&frame);
4690 host_impl_->DidDrawAllLayers(frame);
4691 EXPECT_FALSE(frame.has_no_damage);
4692 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
4694 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4697 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
4698 InputHandlerScrollResult scroll_result;
4699 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4700 host_impl_->SetViewportSize(gfx::Size(50, 50));
4701 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4702 DrawFrame();
4703 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4705 // In-bounds scrolling does not affect overscroll.
4706 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4707 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4708 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4709 EXPECT_TRUE(scroll_result.did_scroll);
4710 EXPECT_FALSE(scroll_result.did_overscroll_root);
4711 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4712 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4714 // Overscroll events are reflected immediately.
4715 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4716 EXPECT_TRUE(scroll_result.did_scroll);
4717 EXPECT_TRUE(scroll_result.did_overscroll_root);
4718 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4719 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4720 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4721 host_impl_->accumulated_root_overscroll());
4723 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4724 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4725 EXPECT_TRUE(scroll_result.did_scroll);
4726 EXPECT_FALSE(scroll_result.did_overscroll_root);
4727 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4728 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4729 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4730 host_impl_->accumulated_root_overscroll());
4732 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4733 EXPECT_FALSE(scroll_result.did_scroll);
4734 EXPECT_TRUE(scroll_result.did_overscroll_root);
4735 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4736 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4737 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4738 host_impl_->accumulated_root_overscroll());
4740 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4741 EXPECT_TRUE(scroll_result.did_scroll);
4742 EXPECT_FALSE(scroll_result.did_overscroll_root);
4743 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4744 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4745 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4746 host_impl_->accumulated_root_overscroll());
4748 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4749 EXPECT_TRUE(scroll_result.did_scroll);
4750 EXPECT_TRUE(scroll_result.did_overscroll_root);
4751 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
4752 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
4753 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4754 host_impl_->accumulated_root_overscroll());
4756 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4757 EXPECT_TRUE(scroll_result.did_scroll);
4758 EXPECT_TRUE(scroll_result.did_overscroll_root);
4759 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4760 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
4761 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4762 host_impl_->accumulated_root_overscroll());
4764 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4765 EXPECT_TRUE(scroll_result.did_scroll);
4766 EXPECT_TRUE(scroll_result.did_overscroll_root);
4767 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4768 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4769 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4770 host_impl_->accumulated_root_overscroll());
4772 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4773 // as no scroll occurs.
4774 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4775 EXPECT_FALSE(scroll_result.did_scroll);
4776 EXPECT_TRUE(scroll_result.did_overscroll_root);
4777 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4778 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
4779 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4780 host_impl_->accumulated_root_overscroll());
4782 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4783 EXPECT_FALSE(scroll_result.did_scroll);
4784 EXPECT_TRUE(scroll_result.did_overscroll_root);
4785 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4786 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
4787 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4788 host_impl_->accumulated_root_overscroll());
4790 // Overscroll resets on valid scroll.
4791 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4792 EXPECT_TRUE(scroll_result.did_scroll);
4793 EXPECT_FALSE(scroll_result.did_overscroll_root);
4794 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4795 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4796 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4797 host_impl_->accumulated_root_overscroll());
4799 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4800 EXPECT_TRUE(scroll_result.did_scroll);
4801 EXPECT_TRUE(scroll_result.did_overscroll_root);
4802 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4803 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4804 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4805 host_impl_->accumulated_root_overscroll());
4807 host_impl_->ScrollEnd();
4811 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
4812 // Scroll child layers beyond their maximum scroll range and make sure root
4813 // overscroll does not accumulate.
4814 InputHandlerScrollResult scroll_result;
4815 gfx::Size surface_size(10, 10);
4816 scoped_ptr<LayerImpl> root_clip =
4817 LayerImpl::Create(host_impl_->active_tree(), 4);
4818 root_clip->SetHasRenderSurface(true);
4820 scoped_ptr<LayerImpl> root =
4821 CreateScrollableLayer(1, surface_size, root_clip.get());
4823 scoped_ptr<LayerImpl> grand_child =
4824 CreateScrollableLayer(3, surface_size, root_clip.get());
4826 scoped_ptr<LayerImpl> child =
4827 CreateScrollableLayer(2, surface_size, root_clip.get());
4828 LayerImpl* grand_child_layer = grand_child.get();
4829 child->AddChild(grand_child.Pass());
4831 LayerImpl* child_layer = child.get();
4832 root->AddChild(child.Pass());
4833 root_clip->AddChild(root.Pass());
4834 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4835 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4836 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4837 host_impl_->active_tree()->DidBecomeActive();
4838 host_impl_->SetViewportSize(surface_size);
4839 DrawFrame();
4841 gfx::Vector2d scroll_delta(0, -10);
4842 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4843 host_impl_->ScrollBegin(gfx::Point(),
4844 InputHandler::NON_BUBBLING_GESTURE));
4845 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4846 EXPECT_TRUE(scroll_result.did_scroll);
4847 EXPECT_FALSE(scroll_result.did_overscroll_root);
4848 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4849 host_impl_->ScrollEnd();
4851 // The next time we scroll we should only scroll the parent, but overscroll
4852 // should still not reach the root layer.
4853 scroll_delta = gfx::Vector2d(0, -30);
4854 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4855 host_impl_->ScrollBegin(gfx::Point(5, 5),
4856 InputHandler::NON_BUBBLING_GESTURE));
4857 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4858 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4859 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4860 EXPECT_TRUE(scroll_result.did_scroll);
4861 EXPECT_FALSE(scroll_result.did_overscroll_root);
4862 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
4863 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4864 host_impl_->ScrollEnd();
4866 // After scrolling the parent, another scroll on the opposite direction
4867 // should scroll the child.
4868 scroll_delta = gfx::Vector2d(0, 70);
4869 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4870 host_impl_->ScrollBegin(gfx::Point(5, 5),
4871 InputHandler::NON_BUBBLING_GESTURE));
4872 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4873 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4874 EXPECT_TRUE(scroll_result.did_scroll);
4875 EXPECT_FALSE(scroll_result.did_overscroll_root);
4876 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4877 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4878 host_impl_->ScrollEnd();
4882 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
4883 // When we try to scroll a non-scrollable child layer, the scroll delta
4884 // should be applied to one of its ancestors if possible. Overscroll should
4885 // be reflected only when it has bubbled up to the root scrolling layer.
4886 InputHandlerScrollResult scroll_result;
4887 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4888 DrawFrame();
4890 gfx::Vector2d scroll_delta(0, 8);
4891 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4892 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4893 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4894 EXPECT_TRUE(scroll_result.did_scroll);
4895 EXPECT_FALSE(scroll_result.did_overscroll_root);
4896 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4897 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4898 EXPECT_TRUE(scroll_result.did_scroll);
4899 EXPECT_TRUE(scroll_result.did_overscroll_root);
4900 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4901 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4902 EXPECT_FALSE(scroll_result.did_scroll);
4903 EXPECT_TRUE(scroll_result.did_overscroll_root);
4904 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4905 host_impl_->ScrollEnd();
4909 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4910 InputHandlerScrollResult scroll_result;
4911 LayerTreeSettings settings;
4912 CreateHostImpl(settings, CreateOutputSurface());
4914 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4915 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4916 clip_layer->SetBounds(gfx::Size(50, 50));
4917 host_impl_->SetViewportSize(gfx::Size(50, 50));
4918 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4919 DrawFrame();
4920 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4922 // Even though the layer can't scroll the overscroll still happens.
4923 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4924 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4925 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4926 EXPECT_FALSE(scroll_result.did_scroll);
4927 EXPECT_TRUE(scroll_result.did_overscroll_root);
4928 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4931 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4932 InputHandlerScrollResult scroll_result;
4933 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4935 DrawFrame();
4937 // Edge glow effect should be applicable only upon reaching Edges
4938 // of the content. unnecessary glow effect calls shouldn't be
4939 // called while scrolling up without reaching the edge of the content.
4940 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4941 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4942 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4943 EXPECT_TRUE(scroll_result.did_scroll);
4944 EXPECT_FALSE(scroll_result.did_overscroll_root);
4945 EXPECT_EQ(gfx::Vector2dF().ToString(),
4946 host_impl_->accumulated_root_overscroll().ToString());
4947 scroll_result =
4948 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4949 EXPECT_TRUE(scroll_result.did_scroll);
4950 EXPECT_FALSE(scroll_result.did_overscroll_root);
4951 EXPECT_EQ(gfx::Vector2dF().ToString(),
4952 host_impl_->accumulated_root_overscroll().ToString());
4953 host_impl_->ScrollEnd();
4954 // unusedrootDelta should be subtracted from applied delta so that
4955 // unwanted glow effect calls are not called.
4956 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4957 host_impl_->ScrollBegin(gfx::Point(0, 0),
4958 InputHandler::NON_BUBBLING_GESTURE));
4959 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
4960 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4961 EXPECT_TRUE(scroll_result.did_scroll);
4962 EXPECT_TRUE(scroll_result.did_overscroll_root);
4963 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4964 host_impl_->accumulated_root_overscroll().ToString());
4966 scroll_result =
4967 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4968 EXPECT_FALSE(scroll_result.did_scroll);
4969 EXPECT_FALSE(scroll_result.did_overscroll_root);
4970 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4971 host_impl_->accumulated_root_overscroll().ToString());
4972 host_impl_->ScrollEnd();
4973 // TestCase to check kEpsilon, which prevents minute values to trigger
4974 // gloweffect without reaching edge.
4975 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4976 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4977 scroll_result =
4978 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4979 EXPECT_FALSE(scroll_result.did_scroll);
4980 EXPECT_FALSE(scroll_result.did_overscroll_root);
4981 EXPECT_EQ(gfx::Vector2dF().ToString(),
4982 host_impl_->accumulated_root_overscroll().ToString());
4983 host_impl_->ScrollEnd();
4987 class BlendStateCheckLayer : public LayerImpl {
4988 public:
4989 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4990 int id,
4991 ResourceProvider* resource_provider) {
4992 return make_scoped_ptr(
4993 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4996 void AppendQuads(RenderPass* render_pass,
4997 AppendQuadsData* append_quads_data) override {
4998 quads_appended_ = true;
5000 gfx::Rect opaque_rect;
5001 if (contents_opaque())
5002 opaque_rect = quad_rect_;
5003 else
5004 opaque_rect = opaque_content_rect_;
5005 gfx::Rect visible_quad_rect = quad_rect_;
5007 SharedQuadState* shared_quad_state =
5008 render_pass->CreateAndAppendSharedQuadState();
5009 PopulateSharedQuadState(shared_quad_state);
5011 TileDrawQuad* test_blending_draw_quad =
5012 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
5013 test_blending_draw_quad->SetNew(shared_quad_state,
5014 quad_rect_,
5015 opaque_rect,
5016 visible_quad_rect,
5017 resource_id_,
5018 gfx::RectF(0.f, 0.f, 1.f, 1.f),
5019 gfx::Size(1, 1),
5020 false,
5021 false);
5022 test_blending_draw_quad->visible_rect = quad_visible_rect_;
5023 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
5024 EXPECT_EQ(has_render_surface_, !!render_surface());
5027 void SetExpectation(bool blend, bool has_render_surface) {
5028 blend_ = blend;
5029 has_render_surface_ = has_render_surface;
5030 quads_appended_ = false;
5033 bool quads_appended() const { return quads_appended_; }
5035 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
5036 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
5037 void SetOpaqueContentRect(const gfx::Rect& rect) {
5038 opaque_content_rect_ = rect;
5041 private:
5042 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
5043 int id,
5044 ResourceProvider* resource_provider)
5045 : LayerImpl(tree_impl, id),
5046 blend_(false),
5047 has_render_surface_(false),
5048 quads_appended_(false),
5049 quad_rect_(5, 5, 5, 5),
5050 quad_visible_rect_(5, 5, 5, 5),
5051 resource_id_(resource_provider->CreateResource(
5052 gfx::Size(1, 1),
5053 GL_CLAMP_TO_EDGE,
5054 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
5055 RGBA_8888)) {
5056 resource_provider->AllocateForTesting(resource_id_);
5057 SetBounds(gfx::Size(10, 10));
5058 SetDrawsContent(true);
5061 bool blend_;
5062 bool has_render_surface_;
5063 bool quads_appended_;
5064 gfx::Rect quad_rect_;
5065 gfx::Rect opaque_content_rect_;
5066 gfx::Rect quad_visible_rect_;
5067 ResourceId resource_id_;
5070 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
5072 scoped_ptr<LayerImpl> root =
5073 LayerImpl::Create(host_impl_->active_tree(), 1);
5074 root->SetBounds(gfx::Size(10, 10));
5075 root->SetDrawsContent(false);
5076 root->SetHasRenderSurface(true);
5077 host_impl_->active_tree()->SetRootLayer(root.Pass());
5079 LayerImpl* root = host_impl_->active_tree()->root_layer();
5081 root->AddChild(
5082 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5084 host_impl_->resource_provider()));
5085 BlendStateCheckLayer* layer1 =
5086 static_cast<BlendStateCheckLayer*>(root->children()[0]);
5087 layer1->SetPosition(gfx::PointF(2.f, 2.f));
5089 LayerTreeHostImpl::FrameData frame;
5091 // Opaque layer, drawn without blending.
5092 layer1->SetContentsOpaque(true);
5093 layer1->SetExpectation(false, false);
5094 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5095 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5096 host_impl_->DrawLayers(&frame);
5097 EXPECT_TRUE(layer1->quads_appended());
5098 host_impl_->DidDrawAllLayers(frame);
5100 // Layer with translucent content and painting, so drawn with blending.
5101 layer1->SetContentsOpaque(false);
5102 layer1->SetExpectation(true, false);
5103 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5104 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5105 host_impl_->DrawLayers(&frame);
5106 EXPECT_TRUE(layer1->quads_appended());
5107 host_impl_->DidDrawAllLayers(frame);
5109 // Layer with translucent opacity, drawn with blending.
5110 layer1->SetContentsOpaque(true);
5111 layer1->SetOpacity(0.5f);
5112 layer1->SetExpectation(true, false);
5113 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5114 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5115 host_impl_->DrawLayers(&frame);
5116 EXPECT_TRUE(layer1->quads_appended());
5117 host_impl_->DidDrawAllLayers(frame);
5119 // Layer with translucent opacity and painting, drawn with blending.
5120 layer1->SetContentsOpaque(true);
5121 layer1->SetOpacity(0.5f);
5122 layer1->SetExpectation(true, false);
5123 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5124 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5125 host_impl_->DrawLayers(&frame);
5126 EXPECT_TRUE(layer1->quads_appended());
5127 host_impl_->DidDrawAllLayers(frame);
5129 layer1->AddChild(
5130 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5132 host_impl_->resource_provider()));
5133 BlendStateCheckLayer* layer2 =
5134 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
5135 layer2->SetPosition(gfx::PointF(4.f, 4.f));
5137 // 2 opaque layers, drawn without blending.
5138 layer1->SetContentsOpaque(true);
5139 layer1->SetOpacity(1.f);
5140 layer1->SetExpectation(false, false);
5141 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5142 layer2->SetContentsOpaque(true);
5143 layer2->SetOpacity(1.f);
5144 layer2->SetExpectation(false, false);
5145 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5146 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5147 host_impl_->DrawLayers(&frame);
5148 EXPECT_TRUE(layer1->quads_appended());
5149 EXPECT_TRUE(layer2->quads_appended());
5150 host_impl_->DidDrawAllLayers(frame);
5152 // Parent layer with translucent content, drawn with blending.
5153 // Child layer with opaque content, drawn without blending.
5154 layer1->SetContentsOpaque(false);
5155 layer1->SetExpectation(true, false);
5156 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5157 layer2->SetExpectation(false, false);
5158 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5159 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5160 host_impl_->DrawLayers(&frame);
5161 EXPECT_TRUE(layer1->quads_appended());
5162 EXPECT_TRUE(layer2->quads_appended());
5163 host_impl_->DidDrawAllLayers(frame);
5165 // Parent layer with translucent content but opaque painting, drawn without
5166 // blending.
5167 // Child layer with opaque content, drawn without blending.
5168 layer1->SetContentsOpaque(true);
5169 layer1->SetExpectation(false, false);
5170 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5171 layer2->SetExpectation(false, false);
5172 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5173 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5174 host_impl_->DrawLayers(&frame);
5175 EXPECT_TRUE(layer1->quads_appended());
5176 EXPECT_TRUE(layer2->quads_appended());
5177 host_impl_->DidDrawAllLayers(frame);
5179 // Parent layer with translucent opacity and opaque content. Since it has a
5180 // drawing child, it's drawn to a render surface which carries the opacity,
5181 // so it's itself drawn without blending.
5182 // Child layer with opaque content, drawn without blending (parent surface
5183 // carries the inherited opacity).
5184 layer1->SetContentsOpaque(true);
5185 layer1->SetOpacity(0.5f);
5186 layer1->SetHasRenderSurface(true);
5187 layer1->SetExpectation(false, true);
5188 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5189 layer2->SetExpectation(false, false);
5190 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5191 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5192 host_impl_->active_tree()->root_layer());
5193 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5194 host_impl_->DrawLayers(&frame);
5195 EXPECT_TRUE(layer1->quads_appended());
5196 EXPECT_TRUE(layer2->quads_appended());
5197 host_impl_->DidDrawAllLayers(frame);
5198 layer1->SetHasRenderSurface(false);
5200 // Draw again, but with child non-opaque, to make sure
5201 // layer1 not culled.
5202 layer1->SetContentsOpaque(true);
5203 layer1->SetOpacity(1.f);
5204 layer1->SetExpectation(false, false);
5205 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5206 layer2->SetContentsOpaque(true);
5207 layer2->SetOpacity(0.5f);
5208 layer2->SetExpectation(true, false);
5209 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5210 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5211 host_impl_->DrawLayers(&frame);
5212 EXPECT_TRUE(layer1->quads_appended());
5213 EXPECT_TRUE(layer2->quads_appended());
5214 host_impl_->DidDrawAllLayers(frame);
5216 // A second way of making the child non-opaque.
5217 layer1->SetContentsOpaque(true);
5218 layer1->SetOpacity(1.f);
5219 layer1->SetExpectation(false, false);
5220 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5221 layer2->SetContentsOpaque(false);
5222 layer2->SetOpacity(1.f);
5223 layer2->SetExpectation(true, false);
5224 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5225 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5226 host_impl_->DrawLayers(&frame);
5227 EXPECT_TRUE(layer1->quads_appended());
5228 EXPECT_TRUE(layer2->quads_appended());
5229 host_impl_->DidDrawAllLayers(frame);
5231 // And when the layer says its not opaque but is painted opaque, it is not
5232 // blended.
5233 layer1->SetContentsOpaque(true);
5234 layer1->SetOpacity(1.f);
5235 layer1->SetExpectation(false, false);
5236 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5237 layer2->SetContentsOpaque(true);
5238 layer2->SetOpacity(1.f);
5239 layer2->SetExpectation(false, false);
5240 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5241 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5242 host_impl_->DrawLayers(&frame);
5243 EXPECT_TRUE(layer1->quads_appended());
5244 EXPECT_TRUE(layer2->quads_appended());
5245 host_impl_->DidDrawAllLayers(frame);
5247 // Layer with partially opaque contents, drawn with blending.
5248 layer1->SetContentsOpaque(false);
5249 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5250 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5251 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5252 layer1->SetExpectation(true, false);
5253 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5254 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5255 host_impl_->DrawLayers(&frame);
5256 EXPECT_TRUE(layer1->quads_appended());
5257 host_impl_->DidDrawAllLayers(frame);
5259 // Layer with partially opaque contents partially culled, drawn with blending.
5260 layer1->SetContentsOpaque(false);
5261 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5262 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5263 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5264 layer1->SetExpectation(true, false);
5265 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5266 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5267 host_impl_->DrawLayers(&frame);
5268 EXPECT_TRUE(layer1->quads_appended());
5269 host_impl_->DidDrawAllLayers(frame);
5271 // Layer with partially opaque contents culled, drawn with blending.
5272 layer1->SetContentsOpaque(false);
5273 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5274 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5275 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5276 layer1->SetExpectation(true, false);
5277 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5278 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5279 host_impl_->DrawLayers(&frame);
5280 EXPECT_TRUE(layer1->quads_appended());
5281 host_impl_->DidDrawAllLayers(frame);
5283 // Layer with partially opaque contents and translucent contents culled, drawn
5284 // without blending.
5285 layer1->SetContentsOpaque(false);
5286 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5287 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5288 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5289 layer1->SetExpectation(false, false);
5290 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5291 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5292 host_impl_->DrawLayers(&frame);
5293 EXPECT_TRUE(layer1->quads_appended());
5294 host_impl_->DidDrawAllLayers(frame);
5297 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
5298 protected:
5299 LayerTreeHostImplViewportCoveredTest() :
5300 gutter_quad_material_(DrawQuad::SOLID_COLOR),
5301 child_(NULL),
5302 did_activate_pending_tree_(false) {}
5304 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
5305 if (always_draw) {
5306 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5308 return FakeOutputSurface::Create3d();
5311 void SetupActiveTreeLayers() {
5312 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
5313 host_impl_->active_tree()->SetRootLayer(
5314 LayerImpl::Create(host_impl_->active_tree(), 1));
5315 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
5316 host_impl_->active_tree()->root_layer()->AddChild(
5317 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5319 host_impl_->resource_provider()));
5320 child_ = static_cast<BlendStateCheckLayer*>(
5321 host_impl_->active_tree()->root_layer()->children()[0]);
5322 child_->SetExpectation(false, false);
5323 child_->SetContentsOpaque(true);
5326 // Expect no gutter rects.
5327 void TestLayerCoversFullViewport() {
5328 gfx::Rect layer_rect(viewport_size_);
5329 child_->SetPosition(layer_rect.origin());
5330 child_->SetBounds(layer_rect.size());
5331 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5332 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5334 LayerTreeHostImpl::FrameData frame;
5335 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5336 ASSERT_EQ(1u, frame.render_passes.size());
5338 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5339 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5340 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5342 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5343 host_impl_->DidDrawAllLayers(frame);
5346 // Expect fullscreen gutter rect.
5347 void TestEmptyLayer() {
5348 gfx::Rect layer_rect(0, 0, 0, 0);
5349 child_->SetPosition(layer_rect.origin());
5350 child_->SetBounds(layer_rect.size());
5351 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5352 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5354 LayerTreeHostImpl::FrameData frame;
5355 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5356 ASSERT_EQ(1u, frame.render_passes.size());
5358 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
5359 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5360 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5362 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5363 host_impl_->DidDrawAllLayers(frame);
5366 // Expect four surrounding gutter rects.
5367 void TestLayerInMiddleOfViewport() {
5368 gfx::Rect layer_rect(500, 500, 200, 200);
5369 child_->SetPosition(layer_rect.origin());
5370 child_->SetBounds(layer_rect.size());
5371 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5372 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5374 LayerTreeHostImpl::FrameData frame;
5375 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5376 ASSERT_EQ(1u, frame.render_passes.size());
5378 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
5379 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
5380 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5382 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5383 host_impl_->DidDrawAllLayers(frame);
5386 // Expect no gutter rects.
5387 void TestLayerIsLargerThanViewport() {
5388 gfx::Rect layer_rect(viewport_size_.width() + 10,
5389 viewport_size_.height() + 10);
5390 child_->SetPosition(layer_rect.origin());
5391 child_->SetBounds(layer_rect.size());
5392 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5393 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5395 LayerTreeHostImpl::FrameData frame;
5396 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5397 ASSERT_EQ(1u, frame.render_passes.size());
5399 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5400 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5401 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5403 host_impl_->DidDrawAllLayers(frame);
5406 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
5408 void set_gutter_quad_material(DrawQuad::Material material) {
5409 gutter_quad_material_ = material;
5411 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
5412 gutter_texture_size_ = gutter_texture_size;
5415 protected:
5416 size_t CountGutterQuads(const QuadList& quad_list) {
5417 size_t num_gutter_quads = 0;
5418 for (const auto& quad : quad_list) {
5419 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
5421 return num_gutter_quads;
5424 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
5425 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5426 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
5429 // Make sure that the texture coordinates match their expectations.
5430 void ValidateTextureDrawQuads(const QuadList& quad_list) {
5431 for (const auto& quad : quad_list) {
5432 if (quad->material != DrawQuad::TEXTURE_CONTENT)
5433 continue;
5434 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
5435 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
5436 gutter_texture_size_, host_impl_->device_scale_factor());
5437 EXPECT_EQ(texture_quad->uv_top_left.x(),
5438 texture_quad->rect.x() / gutter_texture_size_pixels.width());
5439 EXPECT_EQ(texture_quad->uv_top_left.y(),
5440 texture_quad->rect.y() / gutter_texture_size_pixels.height());
5441 EXPECT_EQ(
5442 texture_quad->uv_bottom_right.x(),
5443 texture_quad->rect.right() / gutter_texture_size_pixels.width());
5444 EXPECT_EQ(
5445 texture_quad->uv_bottom_right.y(),
5446 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
5450 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
5451 return gfx::ToRoundedSize(
5452 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
5455 DrawQuad::Material gutter_quad_material_;
5456 gfx::Size gutter_texture_size_;
5457 gfx::Size viewport_size_;
5458 BlendStateCheckLayer* child_;
5459 bool did_activate_pending_tree_;
5462 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
5463 viewport_size_ = gfx::Size(1000, 1000);
5465 bool always_draw = false;
5466 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5468 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5469 SetupActiveTreeLayers();
5470 TestLayerCoversFullViewport();
5471 TestEmptyLayer();
5472 TestLayerInMiddleOfViewport();
5473 TestLayerIsLargerThanViewport();
5476 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
5477 viewport_size_ = gfx::Size(1000, 1000);
5479 bool always_draw = false;
5480 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5482 host_impl_->SetDeviceScaleFactor(2.f);
5483 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5484 SetupActiveTreeLayers();
5485 TestLayerCoversFullViewport();
5486 TestEmptyLayer();
5487 TestLayerInMiddleOfViewport();
5488 TestLayerIsLargerThanViewport();
5491 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
5492 viewport_size_ = gfx::Size(1000, 1000);
5494 bool always_draw = true;
5495 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5497 // Pending tree to force active_tree size invalid. Not used otherwise.
5498 host_impl_->CreatePendingTree();
5499 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5500 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5502 SetupActiveTreeLayers();
5503 TestEmptyLayer();
5504 TestLayerInMiddleOfViewport();
5505 TestLayerIsLargerThanViewport();
5508 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
5509 viewport_size_ = gfx::Size(1000, 1000);
5511 bool always_draw = true;
5512 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5514 // Set larger viewport and activate it to active tree.
5515 host_impl_->CreatePendingTree();
5516 gfx::Size larger_viewport(viewport_size_.width() + 100,
5517 viewport_size_.height() + 100);
5518 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
5519 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5520 host_impl_->ActivateSyncTree();
5521 EXPECT_TRUE(did_activate_pending_tree_);
5522 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
5524 // Shrink pending tree viewport without activating.
5525 host_impl_->CreatePendingTree();
5526 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5527 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5529 SetupActiveTreeLayers();
5530 TestEmptyLayer();
5531 TestLayerInMiddleOfViewport();
5532 TestLayerIsLargerThanViewport();
5535 class FakeDrawableLayerImpl: public LayerImpl {
5536 public:
5537 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5538 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
5540 protected:
5541 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
5542 : LayerImpl(tree_impl, id) {}
5545 // Only reshape when we know we are going to draw. Otherwise, the reshape
5546 // can leave the window at the wrong size if we never draw and the proper
5547 // viewport size is never set.
5548 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
5549 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5550 scoped_ptr<OutputSurface> output_surface(
5551 FakeOutputSurface::Create3d(provider));
5552 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5554 scoped_ptr<LayerImpl> root =
5555 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5556 root->SetBounds(gfx::Size(10, 10));
5557 root->SetDrawsContent(true);
5558 root->SetHasRenderSurface(true);
5559 host_impl_->active_tree()->SetRootLayer(root.Pass());
5560 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
5561 provider->TestContext3d()->clear_reshape_called();
5563 LayerTreeHostImpl::FrameData frame;
5564 host_impl_->SetViewportSize(gfx::Size(10, 10));
5565 host_impl_->SetDeviceScaleFactor(1.f);
5566 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5567 host_impl_->DrawLayers(&frame);
5568 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5569 EXPECT_EQ(provider->TestContext3d()->width(), 10);
5570 EXPECT_EQ(provider->TestContext3d()->height(), 10);
5571 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5572 host_impl_->DidDrawAllLayers(frame);
5573 provider->TestContext3d()->clear_reshape_called();
5575 host_impl_->SetViewportSize(gfx::Size(20, 30));
5576 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5577 host_impl_->DrawLayers(&frame);
5578 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5579 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5580 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5581 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5582 host_impl_->DidDrawAllLayers(frame);
5583 provider->TestContext3d()->clear_reshape_called();
5585 host_impl_->SetDeviceScaleFactor(2.f);
5586 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5587 host_impl_->DrawLayers(&frame);
5588 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5589 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5590 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5591 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
5592 host_impl_->DidDrawAllLayers(frame);
5593 provider->TestContext3d()->clear_reshape_called();
5596 // Make sure damage tracking propagates all the way to the graphics context,
5597 // where it should request to swap only the sub-buffer that is damaged.
5598 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
5599 scoped_refptr<TestContextProvider> context_provider(
5600 TestContextProvider::Create());
5601 context_provider->BindToCurrentThread();
5602 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
5604 scoped_ptr<FakeOutputSurface> output_surface(
5605 FakeOutputSurface::Create3d(context_provider));
5606 FakeOutputSurface* fake_output_surface = output_surface.get();
5608 // This test creates its own LayerTreeHostImpl, so
5609 // that we can force partial swap enabled.
5610 LayerTreeSettings settings;
5611 settings.renderer_settings.partial_swap_enabled = true;
5612 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
5613 LayerTreeHostImpl::Create(
5614 settings, this, &proxy_, &stats_instrumentation_,
5615 &shared_bitmap_manager_, NULL, &task_graph_runner_, 0);
5616 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
5617 layer_tree_host_impl->WillBeginImplFrame(
5618 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5619 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
5621 scoped_ptr<LayerImpl> root =
5622 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
5623 root->SetHasRenderSurface(true);
5624 scoped_ptr<LayerImpl> child =
5625 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
5626 child->SetPosition(gfx::PointF(12.f, 13.f));
5627 child->SetBounds(gfx::Size(14, 15));
5628 child->SetDrawsContent(true);
5629 root->SetBounds(gfx::Size(500, 500));
5630 root->SetDrawsContent(true);
5631 root->AddChild(child.Pass());
5632 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
5634 LayerTreeHostImpl::FrameData frame;
5636 // First frame, the entire screen should get swapped.
5637 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5638 layer_tree_host_impl->DrawLayers(&frame);
5639 layer_tree_host_impl->DidDrawAllLayers(frame);
5640 layer_tree_host_impl->SwapBuffers(frame);
5641 gfx::Rect expected_swap_rect(0, 0, 500, 500);
5642 EXPECT_EQ(expected_swap_rect.ToString(),
5643 fake_output_surface->last_swap_rect().ToString());
5645 // Second frame, only the damaged area should get swapped. Damage should be
5646 // the union of old and new child rects.
5647 // expected damage rect: gfx::Rect(26, 28);
5648 // expected swap rect: vertically flipped, with origin at bottom left corner.
5649 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
5650 gfx::PointF());
5651 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5652 layer_tree_host_impl->DrawLayers(&frame);
5653 host_impl_->DidDrawAllLayers(frame);
5654 layer_tree_host_impl->SwapBuffers(frame);
5656 // Make sure that partial swap is constrained to the viewport dimensions
5657 // expected damage rect: gfx::Rect(500, 500);
5658 // expected swap rect: flipped damage rect, but also clamped to viewport
5659 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
5660 EXPECT_EQ(expected_swap_rect.ToString(),
5661 fake_output_surface->last_swap_rect().ToString());
5663 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
5664 // This will damage everything.
5665 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
5666 SK_ColorBLACK);
5667 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5668 layer_tree_host_impl->DrawLayers(&frame);
5669 host_impl_->DidDrawAllLayers(frame);
5670 layer_tree_host_impl->SwapBuffers(frame);
5672 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
5673 EXPECT_EQ(expected_swap_rect.ToString(),
5674 fake_output_surface->last_swap_rect().ToString());
5677 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
5678 scoped_ptr<LayerImpl> root =
5679 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5680 scoped_ptr<LayerImpl> child =
5681 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
5682 child->SetBounds(gfx::Size(10, 10));
5683 child->SetDrawsContent(true);
5684 root->SetBounds(gfx::Size(10, 10));
5685 root->SetDrawsContent(true);
5686 root->SetHasRenderSurface(true);
5687 root->AddChild(child.Pass());
5689 host_impl_->active_tree()->SetRootLayer(root.Pass());
5691 LayerTreeHostImpl::FrameData frame;
5693 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5694 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
5695 EXPECT_EQ(1u, frame.render_passes.size());
5696 host_impl_->DidDrawAllLayers(frame);
5699 class FakeLayerWithQuads : public LayerImpl {
5700 public:
5701 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5702 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
5705 void AppendQuads(RenderPass* render_pass,
5706 AppendQuadsData* append_quads_data) override {
5707 SharedQuadState* shared_quad_state =
5708 render_pass->CreateAndAppendSharedQuadState();
5709 PopulateSharedQuadState(shared_quad_state);
5711 SkColor gray = SkColorSetRGB(100, 100, 100);
5712 gfx::Rect quad_rect(bounds());
5713 gfx::Rect visible_quad_rect(quad_rect);
5714 SolidColorDrawQuad* my_quad =
5715 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5716 my_quad->SetNew(
5717 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
5720 private:
5721 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
5722 : LayerImpl(tree_impl, id) {}
5725 class MockContext : public TestWebGraphicsContext3D {
5726 public:
5727 MOCK_METHOD1(useProgram, void(GLuint program));
5728 MOCK_METHOD5(uniform4f, void(GLint location,
5729 GLfloat x,
5730 GLfloat y,
5731 GLfloat z,
5732 GLfloat w));
5733 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
5734 GLsizei count,
5735 GLboolean transpose,
5736 const GLfloat* value));
5737 MOCK_METHOD4(drawElements, void(GLenum mode,
5738 GLsizei count,
5739 GLenum type,
5740 GLintptr offset));
5741 MOCK_METHOD1(enable, void(GLenum cap));
5742 MOCK_METHOD1(disable, void(GLenum cap));
5743 MOCK_METHOD4(scissor, void(GLint x,
5744 GLint y,
5745 GLsizei width,
5746 GLsizei height));
5749 class MockContextHarness {
5750 private:
5751 MockContext* context_;
5753 public:
5754 explicit MockContextHarness(MockContext* context)
5755 : context_(context) {
5756 context_->set_have_post_sub_buffer(true);
5758 // Catch "uninteresting" calls
5759 EXPECT_CALL(*context_, useProgram(_))
5760 .Times(0);
5762 EXPECT_CALL(*context_, drawElements(_, _, _, _))
5763 .Times(0);
5765 // These are not asserted
5766 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
5767 .WillRepeatedly(Return());
5769 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
5770 .WillRepeatedly(Return());
5772 // Any un-sanctioned calls to enable() are OK
5773 EXPECT_CALL(*context_, enable(_))
5774 .WillRepeatedly(Return());
5776 // Any un-sanctioned calls to disable() are OK
5777 EXPECT_CALL(*context_, disable(_))
5778 .WillRepeatedly(Return());
5781 void MustDrawSolidQuad() {
5782 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5783 .WillOnce(Return())
5784 .RetiresOnSaturation();
5786 EXPECT_CALL(*context_, useProgram(_))
5787 .WillOnce(Return())
5788 .RetiresOnSaturation();
5791 void MustSetScissor(int x, int y, int width, int height) {
5792 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5793 .WillRepeatedly(Return());
5795 EXPECT_CALL(*context_, scissor(x, y, width, height))
5796 .Times(AtLeast(1))
5797 .WillRepeatedly(Return());
5800 void MustSetNoScissor() {
5801 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5802 .WillRepeatedly(Return());
5804 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5805 .Times(0);
5807 EXPECT_CALL(*context_, scissor(_, _, _, _))
5808 .Times(0);
5812 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5813 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5814 MockContext* mock_context = mock_context_owned.get();
5815 MockContextHarness harness(mock_context);
5817 // Run test case
5818 LayerTreeSettings settings = DefaultSettings();
5819 settings.renderer_settings.partial_swap_enabled = false;
5820 CreateHostImpl(settings,
5821 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5822 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5824 // Without partial swap, and no clipping, no scissor is set.
5825 harness.MustDrawSolidQuad();
5826 harness.MustSetNoScissor();
5828 LayerTreeHostImpl::FrameData frame;
5829 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5830 host_impl_->DrawLayers(&frame);
5831 host_impl_->DidDrawAllLayers(frame);
5833 Mock::VerifyAndClearExpectations(&mock_context);
5835 // Without partial swap, but a layer does clip its subtree, one scissor is
5836 // set.
5837 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5838 harness.MustDrawSolidQuad();
5839 harness.MustSetScissor(0, 0, 10, 10);
5841 LayerTreeHostImpl::FrameData frame;
5842 host_impl_->active_tree()->BuildPropertyTreesForTesting();
5843 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5844 host_impl_->DrawLayers(&frame);
5845 host_impl_->DidDrawAllLayers(frame);
5847 Mock::VerifyAndClearExpectations(&mock_context);
5850 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5851 scoped_ptr<MockContext> context_owned(new MockContext);
5852 MockContext* mock_context = context_owned.get();
5853 MockContextHarness harness(mock_context);
5855 LayerTreeSettings settings = DefaultSettings();
5856 settings.renderer_settings.partial_swap_enabled = true;
5857 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5858 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5860 // The first frame is not a partially-swapped one. No scissor should be set.
5861 harness.MustSetNoScissor();
5862 harness.MustDrawSolidQuad();
5864 LayerTreeHostImpl::FrameData frame;
5865 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5866 host_impl_->DrawLayers(&frame);
5867 host_impl_->DidDrawAllLayers(frame);
5869 Mock::VerifyAndClearExpectations(&mock_context);
5871 // Damage a portion of the frame.
5872 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5873 gfx::Rect(0, 0, 2, 3));
5875 // The second frame will be partially-swapped (the y coordinates are flipped).
5876 harness.MustSetScissor(0, 7, 2, 3);
5877 harness.MustDrawSolidQuad();
5879 LayerTreeHostImpl::FrameData frame;
5880 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5881 host_impl_->DrawLayers(&frame);
5882 host_impl_->DidDrawAllLayers(frame);
5884 Mock::VerifyAndClearExpectations(&mock_context);
5887 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5888 bool partial_swap,
5889 LayerTreeHostImplClient* client,
5890 Proxy* proxy,
5891 SharedBitmapManager* manager,
5892 TaskGraphRunner* task_graph_runner,
5893 RenderingStatsInstrumentation* stats_instrumentation) {
5894 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5895 scoped_ptr<OutputSurface> output_surface(
5896 FakeOutputSurface::Create3d(provider));
5897 provider->BindToCurrentThread();
5898 provider->TestContext3d()->set_have_post_sub_buffer(true);
5900 LayerTreeSettings settings;
5901 settings.renderer_settings.partial_swap_enabled = partial_swap;
5902 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5903 LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation,
5904 manager, nullptr, task_graph_runner, 0);
5905 my_host_impl->InitializeRenderer(output_surface.Pass());
5906 my_host_impl->WillBeginImplFrame(
5907 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5908 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5911 Layers are created as follows:
5913 +--------------------+
5914 | 1 |
5915 | +-----------+ |
5916 | | 2 | |
5917 | | +-------------------+
5918 | | | 3 |
5919 | | +-------------------+
5920 | | | |
5921 | +-----------+ |
5924 +--------------------+
5926 Layers 1, 2 have render surfaces
5928 scoped_ptr<LayerImpl> root =
5929 LayerImpl::Create(my_host_impl->active_tree(), 1);
5930 scoped_ptr<LayerImpl> child =
5931 LayerImpl::Create(my_host_impl->active_tree(), 2);
5932 scoped_ptr<LayerImpl> grand_child =
5933 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5935 gfx::Rect root_rect(0, 0, 100, 100);
5936 gfx::Rect child_rect(10, 10, 50, 50);
5937 gfx::Rect grand_child_rect(5, 5, 150, 150);
5939 root->SetHasRenderSurface(true);
5940 root->SetPosition(root_rect.origin());
5941 root->SetBounds(root_rect.size());
5942 root->draw_properties().visible_layer_rect = root_rect;
5943 root->SetDrawsContent(false);
5944 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5946 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5947 child->SetOpacity(0.5f);
5948 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5949 child->draw_properties().visible_layer_rect = child_rect;
5950 child->SetDrawsContent(false);
5951 child->SetHasRenderSurface(true);
5953 grand_child->SetPosition(grand_child_rect.origin());
5954 grand_child->SetBounds(grand_child_rect.size());
5955 grand_child->draw_properties().visible_layer_rect = grand_child_rect;
5956 grand_child->SetDrawsContent(true);
5958 child->AddChild(grand_child.Pass());
5959 root->AddChild(child.Pass());
5961 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5962 return my_host_impl.Pass();
5965 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5966 TestSharedBitmapManager shared_bitmap_manager;
5967 TestTaskGraphRunner task_graph_runner;
5968 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5969 SetupLayersForOpacity(true, this, &proxy_, &shared_bitmap_manager,
5970 &task_graph_runner, &stats_instrumentation_);
5972 LayerTreeHostImpl::FrameData frame;
5973 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5975 // Verify all quads have been computed
5976 ASSERT_EQ(2U, frame.render_passes.size());
5977 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5978 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5979 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5980 frame.render_passes[0]->quad_list.front()->material);
5981 EXPECT_EQ(DrawQuad::RENDER_PASS,
5982 frame.render_passes[1]->quad_list.front()->material);
5984 my_host_impl->DrawLayers(&frame);
5985 my_host_impl->DidDrawAllLayers(frame);
5989 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5990 TestSharedBitmapManager shared_bitmap_manager;
5991 TestTaskGraphRunner task_graph_runner;
5992 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5993 SetupLayersForOpacity(false, this, &proxy_, &shared_bitmap_manager,
5994 &task_graph_runner, &stats_instrumentation_);
5996 LayerTreeHostImpl::FrameData frame;
5997 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5999 // Verify all quads have been computed
6000 ASSERT_EQ(2U, frame.render_passes.size());
6001 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
6002 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
6003 EXPECT_EQ(DrawQuad::SOLID_COLOR,
6004 frame.render_passes[0]->quad_list.front()->material);
6005 EXPECT_EQ(DrawQuad::RENDER_PASS,
6006 frame.render_passes[1]->quad_list.front()->material);
6008 my_host_impl->DrawLayers(&frame);
6009 my_host_impl->DidDrawAllLayers(frame);
6013 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
6014 scoped_ptr<TestWebGraphicsContext3D> context =
6015 TestWebGraphicsContext3D::Create();
6016 TestWebGraphicsContext3D* context3d = context.get();
6017 scoped_ptr<OutputSurface> output_surface(
6018 FakeOutputSurface::Create3d(context.Pass()));
6019 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6021 scoped_ptr<LayerImpl> root_layer =
6022 LayerImpl::Create(host_impl_->active_tree(), 1);
6023 root_layer->SetBounds(gfx::Size(10, 10));
6024 root_layer->SetHasRenderSurface(true);
6026 scoped_refptr<VideoFrame> softwareFrame =
6027 media::VideoFrame::CreateColorFrame(
6028 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
6029 FakeVideoFrameProvider provider;
6030 provider.set_frame(softwareFrame);
6031 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6032 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
6033 video_layer->SetBounds(gfx::Size(10, 10));
6034 video_layer->SetDrawsContent(true);
6035 root_layer->AddChild(video_layer.Pass());
6037 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
6038 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
6039 io_surface_layer->SetBounds(gfx::Size(10, 10));
6040 io_surface_layer->SetDrawsContent(true);
6041 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
6042 root_layer->AddChild(io_surface_layer.Pass());
6044 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
6046 EXPECT_EQ(0u, context3d->NumTextures());
6048 LayerTreeHostImpl::FrameData frame;
6049 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6050 host_impl_->DrawLayers(&frame);
6051 host_impl_->DidDrawAllLayers(frame);
6052 host_impl_->SwapBuffers(frame);
6054 EXPECT_GT(context3d->NumTextures(), 0u);
6056 // Kill the layer tree.
6057 host_impl_->active_tree()->SetRootLayer(
6058 LayerImpl::Create(host_impl_->active_tree(), 100));
6059 // There should be no textures left in use after.
6060 EXPECT_EQ(0u, context3d->NumTextures());
6063 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
6064 public:
6065 MOCK_METHOD1(useProgram, void(GLuint program));
6066 MOCK_METHOD4(drawElements, void(GLenum mode,
6067 GLsizei count,
6068 GLenum type,
6069 GLintptr offset));
6072 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
6073 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
6074 new MockDrawQuadsToFillScreenContext);
6075 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
6077 // Run test case
6078 LayerTreeSettings settings = DefaultSettings();
6079 settings.renderer_settings.partial_swap_enabled = false;
6080 CreateHostImpl(settings,
6081 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
6082 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6083 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
6085 // Verify one quad is drawn when transparent background set is not set.
6086 host_impl_->active_tree()->set_has_transparent_background(false);
6087 EXPECT_CALL(*mock_context, useProgram(_))
6088 .Times(1);
6089 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
6090 .Times(1);
6091 LayerTreeHostImpl::FrameData frame;
6092 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6093 host_impl_->DrawLayers(&frame);
6094 host_impl_->DidDrawAllLayers(frame);
6095 Mock::VerifyAndClearExpectations(&mock_context);
6097 // Verify no quads are drawn when transparent background is set.
6098 host_impl_->active_tree()->set_has_transparent_background(true);
6099 host_impl_->SetFullRootLayerDamage();
6100 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6101 host_impl_->DrawLayers(&frame);
6102 host_impl_->DidDrawAllLayers(frame);
6103 Mock::VerifyAndClearExpectations(&mock_context);
6106 class LayerTreeHostImplTestWithDelegatingRenderer
6107 : public LayerTreeHostImplTest {
6108 protected:
6109 scoped_ptr<OutputSurface> CreateOutputSurface() override {
6110 return FakeOutputSurface::CreateDelegating3d();
6113 void DrawFrameAndTestDamage(const gfx::Rect& expected_damage) {
6114 bool expect_to_draw = !expected_damage.IsEmpty();
6116 LayerTreeHostImpl::FrameData frame;
6117 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6119 if (!expect_to_draw) {
6120 // With no damage, we don't draw, and no quads are created.
6121 ASSERT_EQ(0u, frame.render_passes.size());
6122 } else {
6123 ASSERT_EQ(1u, frame.render_passes.size());
6125 // Verify the damage rect for the root render pass.
6126 const RenderPass* root_render_pass = frame.render_passes.back();
6127 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
6129 // Verify the root and child layers' quads are generated and not being
6130 // culled.
6131 ASSERT_EQ(2u, root_render_pass->quad_list.size());
6133 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
6134 gfx::Rect expected_child_visible_rect(child->bounds());
6135 EXPECT_EQ(expected_child_visible_rect,
6136 root_render_pass->quad_list.front()->visible_rect);
6138 LayerImpl* root = host_impl_->active_tree()->root_layer();
6139 gfx::Rect expected_root_visible_rect(root->bounds());
6140 EXPECT_EQ(expected_root_visible_rect,
6141 root_render_pass->quad_list.ElementAt(1)->visible_rect);
6144 host_impl_->DrawLayers(&frame);
6145 host_impl_->DidDrawAllLayers(frame);
6146 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
6150 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
6151 scoped_ptr<SolidColorLayerImpl> root =
6152 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6153 root->SetPosition(gfx::PointF());
6154 root->SetBounds(gfx::Size(10, 10));
6155 root->SetDrawsContent(true);
6156 root->SetHasRenderSurface(true);
6158 // Child layer is in the bottom right corner.
6159 scoped_ptr<SolidColorLayerImpl> child =
6160 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
6161 child->SetPosition(gfx::PointF(9.f, 9.f));
6162 child->SetBounds(gfx::Size(1, 1));
6163 child->SetDrawsContent(true);
6164 root->AddChild(child.Pass());
6166 host_impl_->active_tree()->SetRootLayer(root.Pass());
6168 // Draw a frame. In the first frame, the entire viewport should be damaged.
6169 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6170 DrawFrameAndTestDamage(full_frame_damage);
6172 // The second frame has damage that doesn't touch the child layer. Its quads
6173 // should still be generated.
6174 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
6175 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
6176 DrawFrameAndTestDamage(small_damage);
6178 // The third frame should have no damage, so no quads should be generated.
6179 gfx::Rect no_damage;
6180 DrawFrameAndTestDamage(no_damage);
6183 // TODO(reveman): Remove this test and the ability to prevent on demand raster
6184 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
6185 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
6186 LayerTreeSettings settings;
6187 CreateHostImpl(settings, CreateOutputSurface());
6188 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
6191 class FakeMaskLayerImpl : public LayerImpl {
6192 public:
6193 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
6194 int id) {
6195 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
6198 void GetContentsResourceId(ResourceId* resource_id,
6199 gfx::Size* resource_size) const override {
6200 *resource_id = 0;
6203 private:
6204 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
6205 : LayerImpl(tree_impl, id) {}
6208 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
6209 public:
6210 using GLRenderer::ShouldAntialiasQuad;
6213 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
6214 // Due to precision issues (especially on Android), sometimes far
6215 // away quads can end up thinking they need AA.
6216 float device_scale_factor = 4.f / 3.f;
6217 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6218 gfx::Size root_size(2000, 1000);
6219 gfx::Size device_viewport_size =
6220 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
6221 host_impl_->SetViewportSize(device_viewport_size);
6223 host_impl_->CreatePendingTree();
6224 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
6225 16.f);
6227 scoped_ptr<LayerImpl> scoped_root =
6228 LayerImpl::Create(host_impl_->pending_tree(), 1);
6229 LayerImpl* root = scoped_root.get();
6230 root->SetHasRenderSurface(true);
6232 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
6234 scoped_ptr<LayerImpl> scoped_scrolling_layer =
6235 LayerImpl::Create(host_impl_->pending_tree(), 2);
6236 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
6237 root->AddChild(scoped_scrolling_layer.Pass());
6239 gfx::Size content_layer_bounds(100000, 100);
6240 gfx::Size pile_tile_size(3000, 3000);
6241 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
6242 pile_tile_size, content_layer_bounds));
6244 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
6245 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
6246 3, pile);
6247 LayerImpl* content_layer = scoped_content_layer.get();
6248 scrolling_layer->AddChild(scoped_content_layer.Pass());
6249 content_layer->SetBounds(content_layer_bounds);
6250 content_layer->SetDrawsContent(true);
6252 root->SetBounds(root_size);
6254 gfx::ScrollOffset scroll_offset(100000, 0);
6255 scrolling_layer->SetScrollClipLayer(root->id());
6256 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
6258 host_impl_->ActivateSyncTree();
6260 bool update_lcd_text = false;
6261 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
6262 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6264 LayerTreeHostImpl::FrameData frame;
6265 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6267 ASSERT_EQ(1u, frame.render_passes.size());
6268 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
6269 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
6271 bool clipped = false, force_aa = false;
6272 gfx::QuadF device_layer_quad = MathUtil::MapQuad(
6273 quad->shared_quad_state->quad_to_target_transform,
6274 gfx::QuadF(gfx::RectF(quad->shared_quad_state->visible_quad_layer_rect)),
6275 &clipped);
6276 EXPECT_FALSE(clipped);
6277 bool antialiased =
6278 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6279 device_layer_quad, clipped, force_aa);
6280 EXPECT_FALSE(antialiased);
6282 host_impl_->DrawLayers(&frame);
6283 host_impl_->DidDrawAllLayers(frame);
6287 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
6288 public:
6289 CompositorFrameMetadataTest()
6290 : swap_buffers_complete_(0) {}
6292 void DidSwapBuffersCompleteOnImplThread() override {
6293 swap_buffers_complete_++;
6296 int swap_buffers_complete_;
6299 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
6300 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
6302 LayerTreeHostImpl::FrameData frame;
6303 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6304 host_impl_->DrawLayers(&frame);
6305 host_impl_->DidDrawAllLayers(frame);
6307 CompositorFrameAck ack;
6308 host_impl_->ReclaimResources(&ack);
6309 host_impl_->DidSwapBuffersComplete();
6310 EXPECT_EQ(swap_buffers_complete_, 1);
6313 class CountingSoftwareDevice : public SoftwareOutputDevice {
6314 public:
6315 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6317 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
6318 ++frames_began_;
6319 return SoftwareOutputDevice::BeginPaint(damage_rect);
6321 void EndPaint() override {
6322 SoftwareOutputDevice::EndPaint();
6323 ++frames_ended_;
6326 int frames_began_, frames_ended_;
6329 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
6330 // No main thread evictions in resourceless software mode.
6331 set_reduce_memory_result(false);
6332 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
6333 EXPECT_TRUE(CreateHostImpl(
6334 DefaultSettings(),
6335 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device))));
6336 host_impl_->SetViewportSize(gfx::Size(50, 50));
6338 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6340 const gfx::Transform external_transform;
6341 const gfx::Rect external_viewport;
6342 const gfx::Rect external_clip;
6343 const bool resourceless_software_draw = true;
6344 host_impl_->SetExternalDrawConstraints(external_transform,
6345 external_viewport,
6346 external_clip,
6347 external_viewport,
6348 external_transform,
6349 resourceless_software_draw);
6351 EXPECT_EQ(0, software_device->frames_began_);
6352 EXPECT_EQ(0, software_device->frames_ended_);
6354 DrawFrame();
6356 EXPECT_EQ(1, software_device->frames_began_);
6357 EXPECT_EQ(1, software_device->frames_ended_);
6359 // Call another API method that is likely to hit nullptr in this mode.
6360 scoped_refptr<base::trace_event::TracedValue> state =
6361 make_scoped_refptr(new base::trace_event::TracedValue());
6362 host_impl_->ActivationStateAsValueInto(state.get());
6365 TEST_F(LayerTreeHostImplTest,
6366 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
6367 set_reduce_memory_result(false);
6368 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6369 FakeOutputSurface::CreateSoftware(
6370 make_scoped_ptr(new CountingSoftwareDevice))));
6372 const gfx::Transform external_transform;
6373 const gfx::Rect external_viewport;
6374 const gfx::Rect external_clip;
6375 const bool resourceless_software_draw = true;
6376 host_impl_->SetExternalDrawConstraints(external_transform,
6377 external_viewport,
6378 external_clip,
6379 external_viewport,
6380 external_transform,
6381 resourceless_software_draw);
6383 // SolidColorLayerImpl will be drawn.
6384 scoped_ptr<SolidColorLayerImpl> root_layer =
6385 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6387 // VideoLayerImpl will not be drawn.
6388 FakeVideoFrameProvider provider;
6389 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6390 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
6391 video_layer->SetBounds(gfx::Size(10, 10));
6392 video_layer->SetDrawsContent(true);
6393 root_layer->AddChild(video_layer.Pass());
6394 SetupRootLayerImpl(root_layer.Pass());
6396 LayerTreeHostImpl::FrameData frame;
6397 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6398 host_impl_->DrawLayers(&frame);
6399 host_impl_->DidDrawAllLayers(frame);
6401 EXPECT_EQ(1u, frame.will_draw_layers.size());
6402 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
6405 // Checks that we have a non-0 default allocation if we pass a context that
6406 // doesn't support memory management extensions.
6407 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
6408 LayerTreeSettings settings;
6409 host_impl_ = LayerTreeHostImpl::Create(
6410 settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_,
6411 &gpu_memory_buffer_manager_, &task_graph_runner_, 0);
6413 scoped_ptr<OutputSurface> output_surface(
6414 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6415 host_impl_->InitializeRenderer(output_surface.Pass());
6416 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
6419 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6420 ASSERT_TRUE(host_impl_->active_tree());
6422 // RequiresHighResToDraw is set when new output surface is used.
6423 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6425 host_impl_->ResetRequiresHighResToDraw();
6427 host_impl_->SetVisible(false);
6428 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6429 host_impl_->SetVisible(true);
6430 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6431 host_impl_->SetVisible(false);
6432 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6434 host_impl_->ResetRequiresHighResToDraw();
6436 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6437 host_impl_->SetVisible(true);
6438 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6441 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6442 ASSERT_TRUE(host_impl_->active_tree());
6443 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6445 // RequiresHighResToDraw is set when new output surface is used.
6446 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6448 host_impl_->ResetRequiresHighResToDraw();
6450 host_impl_->SetContentIsSuitableForGpuRasterization(true);
6451 host_impl_->SetHasGpuRasterizationTrigger(false);
6452 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6453 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6454 host_impl_->SetHasGpuRasterizationTrigger(true);
6455 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6456 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6457 host_impl_->SetHasGpuRasterizationTrigger(false);
6458 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6459 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6461 host_impl_->ResetRequiresHighResToDraw();
6463 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6464 host_impl_->SetHasGpuRasterizationTrigger(true);
6465 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6466 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6469 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
6470 public:
6471 void SetUp() override {
6472 fake_host_impl_ =
6473 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_,
6474 &shared_bitmap_manager_, &task_graph_runner_);
6475 host_impl_.reset(fake_host_impl_);
6476 host_impl_->InitializeRenderer(CreateOutputSurface());
6477 host_impl_->SetViewportSize(gfx::Size(10, 10));
6480 FakeLayerTreeHostImpl* fake_host_impl_;
6483 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6484 fake_host_impl_->DidModifyTilePriorities();
6485 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6486 fake_host_impl_->SetVisible(false);
6487 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6490 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6491 scoped_ptr<TestWebGraphicsContext3D> context =
6492 TestWebGraphicsContext3D::Create();
6493 TestWebGraphicsContext3D* context3d = context.get();
6494 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6495 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6497 EXPECT_EQ(0u, context3d->NumTextures());
6499 UIResourceId ui_resource_id = 1;
6500 bool is_opaque = false;
6501 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6502 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6503 EXPECT_EQ(1u, context3d->NumTextures());
6504 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6505 EXPECT_NE(0u, id1);
6507 // Multiple requests with the same id is allowed. The previous texture is
6508 // deleted.
6509 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6510 EXPECT_EQ(1u, context3d->NumTextures());
6511 ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6512 EXPECT_NE(0u, id2);
6513 EXPECT_NE(id1, id2);
6515 // Deleting invalid UIResourceId is allowed and does not change state.
6516 host_impl_->DeleteUIResource(-1);
6517 EXPECT_EQ(1u, context3d->NumTextures());
6519 // Should return zero for invalid UIResourceId. Number of textures should
6520 // not change.
6521 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6522 EXPECT_EQ(1u, context3d->NumTextures());
6524 host_impl_->DeleteUIResource(ui_resource_id);
6525 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6526 EXPECT_EQ(0u, context3d->NumTextures());
6528 // Should not change state for multiple deletion on one UIResourceId
6529 host_impl_->DeleteUIResource(ui_resource_id);
6530 EXPECT_EQ(0u, context3d->NumTextures());
6533 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6534 scoped_ptr<TestWebGraphicsContext3D> context =
6535 TestWebGraphicsContext3D::Create();
6536 TestWebGraphicsContext3D* context3d = context.get();
6537 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6539 EXPECT_EQ(0u, context3d->NumTextures());
6541 gfx::Size size(4, 4);
6542 // SkImageInfo has no support for ETC1. The |info| below contains the right
6543 // total pixel size for the bitmap but not the right height and width. The
6544 // correct width/height are passed directly to UIResourceBitmap.
6545 SkImageInfo info =
6546 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6547 skia::RefPtr<SkPixelRef> pixel_ref =
6548 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6549 pixel_ref->setImmutable();
6550 UIResourceBitmap bitmap(pixel_ref, size);
6551 UIResourceId ui_resource_id = 1;
6552 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6553 EXPECT_EQ(1u, context3d->NumTextures());
6554 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6555 EXPECT_NE(0u, id1);
6558 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6561 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6562 scoped_refptr<TestContextProvider> context_provider =
6563 TestContextProvider::Create();
6565 CreateHostImpl(DefaultSettings(),
6566 FakeOutputSurface::Create3d(context_provider));
6568 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6570 ScopedPtrVector<CopyOutputRequest> requests;
6571 requests.push_back(CopyOutputRequest::CreateRequest(
6572 base::Bind(&ShutdownReleasesContext_Callback)));
6574 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6576 LayerTreeHostImpl::FrameData frame;
6577 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6578 host_impl_->DrawLayers(&frame);
6579 host_impl_->DidDrawAllLayers(frame);
6581 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6582 // texture in a texture mailbox.
6583 EXPECT_FALSE(context_provider->HasOneRef());
6584 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6586 host_impl_ = nullptr;
6588 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6589 // released, and the texture deleted.
6590 EXPECT_TRUE(context_provider->HasOneRef());
6591 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6594 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6595 // When flinging via touch, only the child should scroll (we should not
6596 // bubble).
6597 gfx::Size surface_size(10, 10);
6598 gfx::Size content_size(20, 20);
6599 scoped_ptr<LayerImpl> root_clip =
6600 LayerImpl::Create(host_impl_->active_tree(), 3);
6601 root_clip->SetHasRenderSurface(true);
6603 scoped_ptr<LayerImpl> root =
6604 CreateScrollableLayer(1, content_size, root_clip.get());
6605 root->SetIsContainerForFixedPositionLayers(true);
6606 scoped_ptr<LayerImpl> child =
6607 CreateScrollableLayer(2, content_size, root_clip.get());
6609 root->AddChild(child.Pass());
6610 int root_id = root->id();
6611 root_clip->AddChild(root.Pass());
6613 host_impl_->SetViewportSize(surface_size);
6614 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6615 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6616 Layer::INVALID_ID);
6617 host_impl_->active_tree()->DidBecomeActive();
6618 DrawFrame();
6620 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6621 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6623 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6625 gfx::Vector2d scroll_delta(0, 100);
6626 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6627 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6629 host_impl_->ScrollEnd();
6631 scoped_ptr<ScrollAndScaleSet> scroll_info =
6632 host_impl_->ProcessScrollDeltas();
6634 // Only the child should have scrolled.
6635 ASSERT_EQ(1u, scroll_info->scrolls.size());
6636 ExpectNone(*scroll_info.get(), root_id);
6640 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6641 // Scroll a child layer beyond its maximum scroll range and make sure the
6642 // the scroll doesn't bubble up to the parent layer.
6643 gfx::Size surface_size(10, 10);
6644 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6645 root->SetHasRenderSurface(true);
6646 scoped_ptr<LayerImpl> root_scrolling =
6647 CreateScrollableLayer(2, surface_size, root.get());
6649 scoped_ptr<LayerImpl> grand_child =
6650 CreateScrollableLayer(4, surface_size, root.get());
6651 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6653 scoped_ptr<LayerImpl> child =
6654 CreateScrollableLayer(3, surface_size, root.get());
6655 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6656 child->AddChild(grand_child.Pass());
6658 root_scrolling->AddChild(child.Pass());
6659 root->AddChild(root_scrolling.Pass());
6660 host_impl_->active_tree()->SetRootLayer(root.Pass());
6661 host_impl_->active_tree()->DidBecomeActive();
6662 host_impl_->SetViewportSize(surface_size);
6663 DrawFrame();
6665 scoped_ptr<ScrollAndScaleSet> scroll_info;
6666 LayerImpl* child =
6667 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6668 LayerImpl* grand_child = child->children()[0];
6670 gfx::Vector2d scroll_delta(0, -2);
6671 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6672 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6673 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6675 // The grand child should have scrolled up to its limit.
6676 scroll_info = host_impl_->ProcessScrollDeltas();
6677 ASSERT_EQ(1u, scroll_info->scrolls.size());
6678 EXPECT_TRUE(
6679 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6680 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6682 // The child should have received the bubbled delta, but the locked
6683 // scrolling layer should remain set as the grand child.
6684 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6685 scroll_info = host_impl_->ProcessScrollDeltas();
6686 ASSERT_EQ(2u, scroll_info->scrolls.size());
6687 EXPECT_TRUE(
6688 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6689 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(), scroll_delta));
6690 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6692 // The first |ScrollBy| after the fling should re-lock the scrolling
6693 // layer to the first layer that scrolled, which is the child.
6694 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6695 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6696 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6698 // The child should have scrolled up to its limit.
6699 scroll_info = host_impl_->ProcessScrollDeltas();
6700 ASSERT_EQ(2u, scroll_info->scrolls.size());
6701 EXPECT_TRUE(
6702 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6703 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(),
6704 scroll_delta + scroll_delta));
6706 // As the locked layer is at it's limit, no further scrolling can occur.
6707 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6708 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6709 host_impl_->ScrollEnd();
6713 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6714 // When flinging via wheel, the root should eventually scroll (we should
6715 // bubble).
6716 gfx::Size surface_size(10, 10);
6717 gfx::Size content_size(20, 20);
6718 scoped_ptr<LayerImpl> root_clip =
6719 LayerImpl::Create(host_impl_->active_tree(), 3);
6720 root_clip->SetHasRenderSurface(true);
6721 scoped_ptr<LayerImpl> root_scroll =
6722 CreateScrollableLayer(1, content_size, root_clip.get());
6723 int root_scroll_id = root_scroll->id();
6724 scoped_ptr<LayerImpl> child =
6725 CreateScrollableLayer(2, content_size, root_clip.get());
6727 root_scroll->AddChild(child.Pass());
6728 root_clip->AddChild(root_scroll.Pass());
6730 host_impl_->SetViewportSize(surface_size);
6731 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6732 host_impl_->active_tree()->DidBecomeActive();
6733 DrawFrame();
6735 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6736 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6738 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6740 gfx::Vector2d scroll_delta(0, 100);
6741 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6742 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6744 host_impl_->ScrollEnd();
6746 scoped_ptr<ScrollAndScaleSet> scroll_info =
6747 host_impl_->ProcessScrollDeltas();
6749 // The root should have scrolled.
6750 ASSERT_EQ(2u, scroll_info->scrolls.size());
6751 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll_id,
6752 gfx::Vector2d(0, 10)));
6756 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6757 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6758 // we should return SCROLL_UNKNOWN.
6759 gfx::Size content_size(100, 100);
6760 SetupScrollAndContentsLayers(content_size);
6762 int scroll_layer_id = 2;
6763 LayerImpl* scroll_layer =
6764 host_impl_->active_tree()->LayerById(scroll_layer_id);
6765 scroll_layer->SetDrawsContent(true);
6767 int page_scale_layer_id = 5;
6768 LayerImpl* page_scale_layer =
6769 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6771 int occluder_layer_id = 6;
6772 scoped_ptr<LayerImpl> occluder_layer =
6773 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6774 occluder_layer->SetDrawsContent(true);
6775 occluder_layer->SetBounds(content_size);
6776 occluder_layer->SetPosition(gfx::PointF());
6778 // The parent of the occluder is *above* the scroller.
6779 page_scale_layer->AddChild(occluder_layer.Pass());
6781 DrawFrame();
6783 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6784 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6787 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6788 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6789 // is not the first scroller we encounter when walking up from the layer, we
6790 // should also return SCROLL_UNKNOWN.
6791 gfx::Size content_size(100, 100);
6792 SetupScrollAndContentsLayers(content_size);
6794 int scroll_layer_id = 2;
6795 LayerImpl* scroll_layer =
6796 host_impl_->active_tree()->LayerById(scroll_layer_id);
6797 scroll_layer->SetDrawsContent(true);
6799 int occluder_layer_id = 6;
6800 scoped_ptr<LayerImpl> occluder_layer =
6801 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6802 occluder_layer->SetDrawsContent(true);
6803 occluder_layer->SetBounds(content_size);
6804 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6806 int child_scroll_clip_layer_id = 7;
6807 scoped_ptr<LayerImpl> child_scroll_clip =
6808 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6810 int child_scroll_layer_id = 8;
6811 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6812 child_scroll_layer_id, content_size, child_scroll_clip.get());
6814 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6816 child_scroll->AddChild(occluder_layer.Pass());
6817 scroll_layer->AddChild(child_scroll.Pass());
6819 DrawFrame();
6821 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6822 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6825 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
6826 gfx::Size content_size(100, 100);
6827 SetupScrollAndContentsLayers(content_size);
6829 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6831 int scroll_layer_id = 2;
6832 LayerImpl* scroll_layer =
6833 host_impl_->active_tree()->LayerById(scroll_layer_id);
6835 int child_scroll_layer_id = 7;
6836 scoped_ptr<LayerImpl> child_scroll =
6837 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6838 child_scroll->SetDrawsContent(false);
6840 scroll_layer->AddChild(child_scroll.Pass());
6842 DrawFrame();
6844 // We should not have scrolled |child_scroll| even though we technically "hit"
6845 // it. The reason for this is that if the scrolling the scroll would not move
6846 // any layer that is a drawn RSLL member, then we can ignore the hit.
6848 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6849 // started scrolling the inner viewport.
6850 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6851 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6853 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6856 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
6857 gfx::Size content_size(100, 100);
6858 SetupScrollAndContentsLayers(content_size);
6860 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6861 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
6863 scoped_ptr<LayerImpl> invisible_scroll_layer =
6864 CreateScrollableLayer(7, content_size, root);
6865 invisible_scroll_layer->SetDrawsContent(false);
6867 scoped_ptr<LayerImpl> child_layer =
6868 LayerImpl::Create(host_impl_->active_tree(), 8);
6869 child_layer->SetDrawsContent(false);
6871 scoped_ptr<LayerImpl> grand_child_layer =
6872 LayerImpl::Create(host_impl_->active_tree(), 9);
6873 grand_child_layer->SetDrawsContent(true);
6874 grand_child_layer->SetBounds(content_size);
6875 // Move the grand child so it's not hit by our test point.
6876 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
6878 child_layer->AddChild(grand_child_layer.Pass());
6879 invisible_scroll_layer->AddChild(child_layer.Pass());
6880 root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
6882 DrawFrame();
6884 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6885 // a descendant which is a drawn RSLL member.
6886 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6887 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6889 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6892 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6893 // This test case is very similar to the one above with one key difference:
6894 // the invisible scroller has a scroll child that is indeed draw contents.
6895 // If we attempt to initiate a gesture scroll off of the visible scroll child
6896 // we should still start the scroll child.
6897 gfx::Size content_size(100, 100);
6898 SetupScrollAndContentsLayers(content_size);
6900 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6902 int scroll_layer_id = 2;
6903 LayerImpl* scroll_layer =
6904 host_impl_->active_tree()->LayerById(scroll_layer_id);
6906 int scroll_child_id = 6;
6907 scoped_ptr<LayerImpl> scroll_child =
6908 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6909 scroll_child->SetDrawsContent(true);
6910 scroll_child->SetBounds(content_size);
6911 // Move the scroll child so it's not hit by our test point.
6912 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6914 int invisible_scroll_layer_id = 7;
6915 scoped_ptr<LayerImpl> invisible_scroll =
6916 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6917 invisible_scroll->SetDrawsContent(false);
6919 int container_id = 8;
6920 scoped_ptr<LayerImpl> container =
6921 LayerImpl::Create(host_impl_->active_tree(), container_id);
6923 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6924 scroll_children->insert(scroll_child.get());
6925 invisible_scroll->SetScrollChildren(scroll_children.release());
6927 scroll_child->SetScrollParent(invisible_scroll.get());
6929 container->AddChild(invisible_scroll.Pass());
6930 container->AddChild(scroll_child.Pass());
6932 scroll_layer->AddChild(container.Pass());
6934 DrawFrame();
6936 // We should have scrolled |child_scroll| even though it is invisible.
6937 // The reason for this is that if the scrolling the scroll would move a layer
6938 // that is a drawn RSLL member, then we should accept this hit.
6939 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6940 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6942 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6945 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6946 // to CompositorFrameMetadata after SwapBuffers();
6947 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6948 scoped_ptr<SolidColorLayerImpl> root =
6949 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6950 root->SetPosition(gfx::PointF());
6951 root->SetBounds(gfx::Size(10, 10));
6952 root->SetDrawsContent(true);
6953 root->SetHasRenderSurface(true);
6955 host_impl_->active_tree()->SetRootLayer(root.Pass());
6957 FakeOutputSurface* fake_output_surface =
6958 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6960 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6961 fake_output_surface->last_sent_frame().metadata.latency_info;
6962 EXPECT_TRUE(metadata_latency_before.empty());
6964 ui::LatencyInfo latency_info;
6965 latency_info.AddLatencyNumber(
6966 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6967 scoped_ptr<SwapPromise> swap_promise(
6968 new LatencyInfoSwapPromise(latency_info));
6969 host_impl_->active_tree()->QueuePinnedSwapPromise(swap_promise.Pass());
6970 host_impl_->SetNeedsRedraw();
6972 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6973 LayerTreeHostImpl::FrameData frame;
6974 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6975 host_impl_->DrawLayers(&frame);
6976 host_impl_->DidDrawAllLayers(frame);
6977 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6979 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6980 fake_output_surface->last_sent_frame().metadata.latency_info;
6981 EXPECT_EQ(1u, metadata_latency_after.size());
6982 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6983 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6986 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6987 int root_layer_id = 1;
6988 scoped_ptr<SolidColorLayerImpl> root =
6989 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6990 root->SetPosition(gfx::PointF());
6991 root->SetBounds(gfx::Size(10, 10));
6992 root->SetDrawsContent(true);
6993 root->SetHasRenderSurface(true);
6995 host_impl_->active_tree()->SetRootLayer(root.Pass());
6997 // Ensure the default frame selection bounds are empty.
6998 FakeOutputSurface* fake_output_surface =
6999 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
7000 const ViewportSelection& selection_before =
7001 fake_output_surface->last_sent_frame().metadata.selection;
7002 EXPECT_EQ(ViewportSelectionBound(), selection_before.start);
7003 EXPECT_EQ(ViewportSelectionBound(), selection_before.end);
7005 // Plumb the layer-local selection bounds.
7006 gfx::PointF selection_top(5, 0);
7007 gfx::PointF selection_bottom(5, 5);
7008 LayerSelection selection;
7009 selection.start.type = SELECTION_BOUND_CENTER;
7010 selection.start.layer_id = root_layer_id;
7011 selection.start.edge_bottom = selection_bottom;
7012 selection.start.edge_top = selection_top;
7013 selection.end = selection.start;
7014 host_impl_->active_tree()->RegisterSelection(selection);
7016 // Trigger a draw-swap sequence.
7017 host_impl_->SetNeedsRedraw();
7019 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7020 LayerTreeHostImpl::FrameData frame;
7021 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7022 host_impl_->DrawLayers(&frame);
7023 host_impl_->DidDrawAllLayers(frame);
7024 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7026 // Ensure the selection bounds have propagated to the frame metadata.
7027 const ViewportSelection& selection_after =
7028 fake_output_surface->last_sent_frame().metadata.selection;
7029 EXPECT_EQ(selection.start.type, selection_after.start.type);
7030 EXPECT_EQ(selection.end.type, selection_after.end.type);
7031 EXPECT_EQ(selection_bottom, selection_after.start.edge_bottom);
7032 EXPECT_EQ(selection_top, selection_after.start.edge_top);
7033 EXPECT_TRUE(selection_after.start.visible);
7034 EXPECT_TRUE(selection_after.start.visible);
7037 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
7038 public:
7039 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
7040 LayerTreeHostImpl* layer_tree_host_impl,
7041 int* set_needs_commit_count,
7042 int* set_needs_redraw_count,
7043 int* forward_to_main_count)
7044 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
7045 set_needs_commit_count_(set_needs_commit_count),
7046 set_needs_redraw_count_(set_needs_redraw_count),
7047 forward_to_main_count_(forward_to_main_count) {}
7049 ~SimpleSwapPromiseMonitor() override {}
7051 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
7053 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
7055 void OnForwardScrollUpdateToMainThreadOnImpl() override {
7056 (*forward_to_main_count_)++;
7059 private:
7060 int* set_needs_commit_count_;
7061 int* set_needs_redraw_count_;
7062 int* forward_to_main_count_;
7065 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
7066 int set_needs_commit_count = 0;
7067 int set_needs_redraw_count = 0;
7068 int forward_to_main_count = 0;
7071 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7072 new SimpleSwapPromiseMonitor(NULL,
7073 host_impl_.get(),
7074 &set_needs_commit_count,
7075 &set_needs_redraw_count,
7076 &forward_to_main_count));
7077 host_impl_->SetNeedsRedraw();
7078 EXPECT_EQ(0, set_needs_commit_count);
7079 EXPECT_EQ(1, set_needs_redraw_count);
7080 EXPECT_EQ(0, forward_to_main_count);
7083 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7084 // monitored.
7085 host_impl_->SetNeedsRedraw();
7086 EXPECT_EQ(0, set_needs_commit_count);
7087 EXPECT_EQ(1, set_needs_redraw_count);
7088 EXPECT_EQ(0, forward_to_main_count);
7091 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7092 new SimpleSwapPromiseMonitor(NULL,
7093 host_impl_.get(),
7094 &set_needs_commit_count,
7095 &set_needs_redraw_count,
7096 &forward_to_main_count));
7097 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
7098 EXPECT_EQ(0, set_needs_commit_count);
7099 EXPECT_EQ(2, set_needs_redraw_count);
7100 EXPECT_EQ(0, forward_to_main_count);
7104 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7105 new SimpleSwapPromiseMonitor(NULL,
7106 host_impl_.get(),
7107 &set_needs_commit_count,
7108 &set_needs_redraw_count,
7109 &forward_to_main_count));
7110 // Empty damage rect won't signal the monitor.
7111 host_impl_->SetNeedsRedrawRect(gfx::Rect());
7112 EXPECT_EQ(0, set_needs_commit_count);
7113 EXPECT_EQ(2, set_needs_redraw_count);
7114 EXPECT_EQ(0, forward_to_main_count);
7118 set_needs_commit_count = 0;
7119 set_needs_redraw_count = 0;
7120 forward_to_main_count = 0;
7121 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7122 new SimpleSwapPromiseMonitor(NULL,
7123 host_impl_.get(),
7124 &set_needs_commit_count,
7125 &set_needs_redraw_count,
7126 &forward_to_main_count));
7127 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7129 // Scrolling normally should not trigger any forwarding.
7130 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7131 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7132 EXPECT_TRUE(
7133 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7134 host_impl_->ScrollEnd();
7136 EXPECT_EQ(0, set_needs_commit_count);
7137 EXPECT_EQ(1, set_needs_redraw_count);
7138 EXPECT_EQ(0, forward_to_main_count);
7140 // Scrolling with a scroll handler should defer the swap to the main
7141 // thread.
7142 scroll_layer->SetHaveScrollEventHandlers(true);
7143 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7144 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7145 EXPECT_TRUE(
7146 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7147 host_impl_->ScrollEnd();
7149 EXPECT_EQ(0, set_needs_commit_count);
7150 EXPECT_EQ(2, set_needs_redraw_count);
7151 EXPECT_EQ(1, forward_to_main_count);
7155 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
7156 public:
7157 void SetUp() override {
7158 LayerTreeSettings settings = DefaultSettings();
7159 CreateHostImpl(settings, CreateOutputSurface());
7160 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
7161 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
7162 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
7165 protected:
7166 static const int top_controls_height_;
7169 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
7171 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
7172 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7173 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7174 BeginFrameArgs begin_frame_args =
7175 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
7176 host_impl_->WillBeginImplFrame(begin_frame_args);
7177 host_impl_->Animate();
7178 EXPECT_FALSE(did_request_redraw_);
7179 host_impl_->DidFinishImplFrame();
7182 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
7183 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7184 EXPECT_FALSE(did_request_redraw_);
7185 host_impl_->CreatePendingTree();
7186 host_impl_->sync_tree()->set_top_controls_height(100);
7187 host_impl_->ActivateSyncTree();
7188 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
7191 TEST_F(LayerTreeHostImplWithTopControlsTest,
7192 TopControlsStayFullyVisibleOnHeightChange) {
7193 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7194 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7196 host_impl_->CreatePendingTree();
7197 host_impl_->sync_tree()->set_top_controls_height(0);
7198 host_impl_->ActivateSyncTree();
7199 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7201 host_impl_->CreatePendingTree();
7202 host_impl_->sync_tree()->set_top_controls_height(50);
7203 host_impl_->ActivateSyncTree();
7204 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7207 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
7208 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7209 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7210 host_impl_->DidChangeTopControlsPosition();
7211 EXPECT_TRUE(did_request_animate_);
7212 EXPECT_TRUE(did_request_redraw_);
7215 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
7216 InputHandlerScrollResult result;
7217 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7218 host_impl_->SetViewportSize(gfx::Size(100, 100));
7219 host_impl_->top_controls_manager()->UpdateTopControlsState(
7220 BOTH, SHOWN, false);
7221 DrawFrame();
7223 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7224 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7225 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7226 EXPECT_EQ(gfx::Vector2dF().ToString(),
7227 scroll_layer->CurrentScrollOffset().ToString());
7229 // Scroll just the top controls and verify that the scroll succeeds.
7230 const float residue = 10;
7231 float offset = top_controls_height_ - residue;
7232 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7233 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7234 EXPECT_TRUE(result.did_scroll);
7235 EXPECT_FLOAT_EQ(-offset,
7236 host_impl_->top_controls_manager()->ControlsTopOffset());
7237 EXPECT_EQ(gfx::Vector2dF().ToString(),
7238 scroll_layer->CurrentScrollOffset().ToString());
7240 // Scroll across the boundary
7241 const float content_scroll = 20;
7242 offset = residue + content_scroll;
7243 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7244 EXPECT_TRUE(result.did_scroll);
7245 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7246 EXPECT_EQ(-top_controls_height_,
7247 host_impl_->top_controls_manager()->ControlsTopOffset());
7248 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
7249 scroll_layer->CurrentScrollOffset().ToString());
7251 // Now scroll back to the top of the content
7252 offset = -content_scroll;
7253 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7254 EXPECT_TRUE(result.did_scroll);
7255 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7256 EXPECT_EQ(-top_controls_height_,
7257 host_impl_->top_controls_manager()->ControlsTopOffset());
7258 EXPECT_EQ(gfx::Vector2dF().ToString(),
7259 scroll_layer->CurrentScrollOffset().ToString());
7261 // And scroll the top controls completely into view
7262 offset = -top_controls_height_;
7263 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7264 EXPECT_TRUE(result.did_scroll);
7265 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7266 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7267 EXPECT_EQ(gfx::Vector2dF().ToString(),
7268 scroll_layer->CurrentScrollOffset().ToString());
7270 // And attempt to scroll past the end
7271 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7272 EXPECT_FALSE(result.did_scroll);
7273 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50));
7274 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7275 EXPECT_EQ(gfx::Vector2dF().ToString(),
7276 scroll_layer->CurrentScrollOffset().ToString());
7278 host_impl_->ScrollEnd();
7281 TEST_F(LayerTreeHostImplWithTopControlsTest, WheelUnhandledByTopControls) {
7282 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7283 host_impl_->SetViewportSize(gfx::Size(50, 100));
7284 host_impl_->active_tree()->set_top_controls_shrink_blink_size(true);
7285 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7286 false);
7287 DrawFrame();
7289 LayerImpl* viewport_layer = host_impl_->InnerViewportScrollLayer();
7291 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7292 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7293 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7294 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer->CurrentScrollOffset());
7296 // Wheel scrolls should not affect the top controls, and should pass
7297 // directly through to the viewport.
7298 const float delta = top_controls_height_;
7299 EXPECT_TRUE(
7300 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
7301 EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7302 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta),
7303 viewport_layer->CurrentScrollOffset());
7305 EXPECT_TRUE(
7306 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
7307 EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7308 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta * 2),
7309 viewport_layer->CurrentScrollOffset());
7312 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
7313 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7314 host_impl_->SetViewportSize(gfx::Size(100, 200));
7315 host_impl_->top_controls_manager()->UpdateTopControlsState(
7316 BOTH, SHOWN, false);
7317 DrawFrame();
7319 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7320 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7321 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7322 EXPECT_EQ(gfx::Vector2dF().ToString(),
7323 scroll_layer->CurrentScrollOffset().ToString());
7325 // Scroll the top controls partially.
7326 const float residue = 35;
7327 float offset = top_controls_height_ - residue;
7328 EXPECT_TRUE(
7329 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7330 EXPECT_FLOAT_EQ(-offset,
7331 host_impl_->top_controls_manager()->ControlsTopOffset());
7332 EXPECT_EQ(gfx::Vector2dF().ToString(),
7333 scroll_layer->CurrentScrollOffset().ToString());
7335 did_request_redraw_ = false;
7336 did_request_animate_ = false;
7337 did_request_commit_ = false;
7339 // End the scroll while the controls are still offset from their limit.
7340 host_impl_->ScrollEnd();
7341 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7342 EXPECT_TRUE(did_request_animate_);
7343 EXPECT_TRUE(did_request_redraw_);
7344 EXPECT_FALSE(did_request_commit_);
7346 // The top controls should properly animate until finished, despite the scroll
7347 // offset being at the origin.
7348 BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
7349 BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
7350 while (did_request_animate_) {
7351 did_request_redraw_ = false;
7352 did_request_animate_ = false;
7353 did_request_commit_ = false;
7355 float old_offset =
7356 host_impl_->top_controls_manager()->ControlsTopOffset();
7358 begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
7359 host_impl_->WillBeginImplFrame(begin_frame_args);
7360 host_impl_->Animate();
7361 EXPECT_EQ(gfx::Vector2dF().ToString(),
7362 scroll_layer->CurrentScrollOffset().ToString());
7364 float new_offset =
7365 host_impl_->top_controls_manager()->ControlsTopOffset();
7367 // No commit is needed as the controls are animating the content offset,
7368 // not the scroll offset.
7369 EXPECT_FALSE(did_request_commit_);
7371 if (new_offset != old_offset)
7372 EXPECT_TRUE(did_request_redraw_);
7374 if (new_offset != 0) {
7375 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
7376 EXPECT_TRUE(did_request_animate_);
7378 host_impl_->DidFinishImplFrame();
7380 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7383 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
7384 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7385 host_impl_->SetViewportSize(gfx::Size(100, 100));
7386 host_impl_->top_controls_manager()->UpdateTopControlsState(
7387 BOTH, SHOWN, false);
7388 float initial_scroll_offset = 50;
7389 scroll_layer->PushScrollOffsetFromMainThread(
7390 gfx::ScrollOffset(0, initial_scroll_offset));
7391 DrawFrame();
7393 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7394 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7395 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7396 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7397 scroll_layer->CurrentScrollOffset().ToString());
7399 // Scroll the top controls partially.
7400 const float residue = 15;
7401 float offset = top_controls_height_ - residue;
7402 EXPECT_TRUE(
7403 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7404 EXPECT_FLOAT_EQ(-offset,
7405 host_impl_->top_controls_manager()->ControlsTopOffset());
7406 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7407 scroll_layer->CurrentScrollOffset().ToString());
7409 did_request_redraw_ = false;
7410 did_request_animate_ = false;
7411 did_request_commit_ = false;
7413 // End the scroll while the controls are still offset from the limit.
7414 host_impl_->ScrollEnd();
7415 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7416 EXPECT_TRUE(did_request_animate_);
7417 EXPECT_TRUE(did_request_redraw_);
7418 EXPECT_FALSE(did_request_commit_);
7420 // Animate the top controls to the limit.
7421 BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
7422 BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
7423 while (did_request_animate_) {
7424 did_request_redraw_ = false;
7425 did_request_animate_ = false;
7426 did_request_commit_ = false;
7428 float old_offset =
7429 host_impl_->top_controls_manager()->ControlsTopOffset();
7431 begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
7432 host_impl_->WillBeginImplFrame(begin_frame_args);
7433 host_impl_->Animate();
7435 float new_offset =
7436 host_impl_->top_controls_manager()->ControlsTopOffset();
7438 if (new_offset != old_offset) {
7439 EXPECT_TRUE(did_request_redraw_);
7440 EXPECT_TRUE(did_request_commit_);
7442 host_impl_->DidFinishImplFrame();
7444 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7445 EXPECT_EQ(-top_controls_height_,
7446 host_impl_->top_controls_manager()->ControlsTopOffset());
7449 TEST_F(LayerTreeHostImplWithTopControlsTest,
7450 TopControlsAnimationAfterMainThreadFlingStopped) {
7451 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7452 host_impl_->SetViewportSize(gfx::Size(100, 100));
7453 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7454 false);
7455 float initial_scroll_offset = 50;
7456 scroll_layer->PushScrollOffsetFromMainThread(
7457 gfx::ScrollOffset(0, initial_scroll_offset));
7458 DrawFrame();
7460 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7461 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7462 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7463 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7464 scroll_layer->CurrentScrollOffset().ToString());
7466 // Scroll the top controls partially.
7467 const float residue = 15;
7468 float offset = top_controls_height_ - residue;
7469 EXPECT_TRUE(
7470 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7471 EXPECT_FLOAT_EQ(-offset,
7472 host_impl_->top_controls_manager()->ControlsTopOffset());
7473 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7474 scroll_layer->CurrentScrollOffset().ToString());
7476 did_request_redraw_ = false;
7477 did_request_animate_ = false;
7478 did_request_commit_ = false;
7480 // End the fling while the controls are still offset from the limit.
7481 host_impl_->MainThreadHasStoppedFlinging();
7482 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7483 EXPECT_TRUE(did_request_animate_);
7484 EXPECT_TRUE(did_request_redraw_);
7485 EXPECT_FALSE(did_request_commit_);
7487 // Animate the top controls to the limit.
7488 BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
7489 BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
7490 while (did_request_animate_) {
7491 did_request_redraw_ = false;
7492 did_request_animate_ = false;
7493 did_request_commit_ = false;
7495 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7497 begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
7498 host_impl_->WillBeginImplFrame(begin_frame_args);
7499 host_impl_->Animate();
7501 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7503 if (new_offset != old_offset) {
7504 EXPECT_TRUE(did_request_redraw_);
7505 EXPECT_TRUE(did_request_commit_);
7507 host_impl_->DidFinishImplFrame();
7509 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7510 EXPECT_EQ(-top_controls_height_,
7511 host_impl_->top_controls_manager()->ControlsTopOffset());
7514 TEST_F(LayerTreeHostImplWithTopControlsTest,
7515 TopControlsScrollDeltaInOverScroll) {
7516 // Verifies that the overscroll delta should not have accumulated in
7517 // the top controls if we do a hide and show without releasing finger.
7519 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7520 host_impl_->SetViewportSize(gfx::Size(100, 100));
7521 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7522 false);
7523 DrawFrame();
7525 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7526 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7527 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7529 float offset = 50;
7530 EXPECT_TRUE(
7531 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7532 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7533 EXPECT_EQ(gfx::Vector2dF().ToString(),
7534 scroll_layer->CurrentScrollOffset().ToString());
7536 EXPECT_TRUE(
7537 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7538 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7539 scroll_layer->CurrentScrollOffset().ToString());
7541 EXPECT_TRUE(
7542 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7544 // Should have fully scrolled
7545 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7546 scroll_layer->CurrentScrollOffset().ToString());
7548 float overscrollamount = 10;
7550 // Overscroll the content
7551 EXPECT_FALSE(
7552 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7553 .did_scroll);
7554 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7555 scroll_layer->CurrentScrollOffset().ToString());
7556 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7557 host_impl_->accumulated_root_overscroll().ToString());
7559 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7560 .did_scroll);
7561 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7562 scroll_layer->CurrentScrollOffset().ToString());
7563 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7565 EXPECT_TRUE(
7566 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7567 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7568 scroll_layer->CurrentScrollOffset().ToString());
7570 // Top controls should be fully visible
7571 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7573 host_impl_->ScrollEnd();
7576 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7577 public:
7578 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7579 const gfx::Size& outer_viewport,
7580 const gfx::Size& inner_viewport) {
7581 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7582 const int kOuterViewportClipLayerId = 6;
7583 const int kOuterViewportScrollLayerId = 7;
7584 const int kInnerViewportScrollLayerId = 2;
7585 const int kInnerViewportClipLayerId = 4;
7586 const int kPageScaleLayerId = 5;
7588 scoped_ptr<LayerImpl> inner_scroll =
7589 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7590 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7591 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7593 scoped_ptr<LayerImpl> inner_clip =
7594 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7595 inner_clip->SetBounds(inner_viewport);
7597 scoped_ptr<LayerImpl> page_scale =
7598 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7600 inner_scroll->SetScrollClipLayer(inner_clip->id());
7601 inner_scroll->SetBounds(outer_viewport);
7602 inner_scroll->SetPosition(gfx::PointF());
7604 scoped_ptr<LayerImpl> outer_clip =
7605 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7606 outer_clip->SetBounds(outer_viewport);
7607 outer_clip->SetIsContainerForFixedPositionLayers(true);
7609 scoped_ptr<LayerImpl> outer_scroll =
7610 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7611 outer_scroll->SetScrollClipLayer(outer_clip->id());
7612 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7613 outer_scroll->SetBounds(content_size);
7614 outer_scroll->SetPosition(gfx::PointF());
7616 scoped_ptr<LayerImpl> contents =
7617 LayerImpl::Create(layer_tree_impl, 8);
7618 contents->SetDrawsContent(true);
7619 contents->SetBounds(content_size);
7620 contents->SetPosition(gfx::PointF());
7622 outer_scroll->AddChild(contents.Pass());
7623 outer_clip->AddChild(outer_scroll.Pass());
7624 inner_scroll->AddChild(outer_clip.Pass());
7625 page_scale->AddChild(inner_scroll.Pass());
7626 inner_clip->AddChild(page_scale.Pass());
7628 inner_clip->SetHasRenderSurface(true);
7629 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7630 layer_tree_impl->SetViewportLayersFromIds(
7631 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7632 kOuterViewportScrollLayerId);
7634 host_impl_->active_tree()->DidBecomeActive();
7638 TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
7639 gfx::Size content_size = gfx::Size(100, 160);
7640 gfx::Size outer_viewport = gfx::Size(50, 80);
7641 gfx::Size inner_viewport = gfx::Size(25, 40);
7643 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7645 TestScrollOffsetDelegate scroll_delegate;
7646 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
7648 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7649 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7650 DrawFrame();
7652 gfx::ScrollOffset inner_expected;
7653 gfx::ScrollOffset outer_expected;
7654 EXPECT_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7655 EXPECT_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7657 gfx::ScrollOffset current_offset(70.f, 100.f);
7659 scroll_delegate.set_getter_return_value(current_offset);
7660 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
7661 EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
7662 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
7664 // Outer viewport scrolls first. Then the rest is applied to the inner
7665 // viewport.
7666 EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f),
7667 inner_scroll->CurrentScrollOffset());
7668 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f),
7669 outer_scroll->CurrentScrollOffset());
7673 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7674 gfx::Size content_size = gfx::Size(100, 160);
7675 gfx::Size outer_viewport = gfx::Size(50, 80);
7676 gfx::Size inner_viewport = gfx::Size(25, 40);
7678 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7680 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7681 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7682 DrawFrame();
7684 gfx::Vector2dF inner_expected;
7685 gfx::Vector2dF outer_expected;
7686 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7687 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7689 // Make sure the fling goes to the outer viewport first
7690 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7691 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7692 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7693 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7694 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7696 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7697 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7698 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7699 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), outer_scroll);
7701 host_impl_->ScrollEnd();
7702 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7704 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7705 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7707 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7708 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7709 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7710 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7711 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7712 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7714 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7715 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7716 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7718 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7719 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7720 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7722 host_impl_->ScrollEnd();
7723 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7725 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7726 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7730 TEST_F(LayerTreeHostImplVirtualViewportTest,
7731 DiagonalScrollBubblesPerfectlyToInner) {
7732 gfx::Size content_size = gfx::Size(100, 160);
7733 gfx::Size outer_viewport = gfx::Size(50, 80);
7734 gfx::Size inner_viewport = gfx::Size(25, 40);
7736 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7738 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7739 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7740 DrawFrame();
7742 gfx::Vector2dF inner_expected;
7743 gfx::Vector2dF outer_expected;
7744 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7745 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7747 // Make sure the scroll goes to the outer viewport first.
7748 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7749 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7750 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7751 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7752 InputHandler::GESTURE));
7754 // Scroll near the edge of the outer viewport.
7755 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7756 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7757 outer_expected += scroll_delta;
7758 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7759 InputHandler::GESTURE));
7761 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7762 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7764 // Now diagonal scroll across the outer viewport boundary in a single event.
7765 // The entirety of the scroll should be consumed, as bubbling between inner
7766 // and outer viewport layers is perfect.
7767 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7768 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7769 InputHandler::GESTURE));
7770 outer_expected += scroll_delta;
7771 inner_expected += scroll_delta;
7772 host_impl_->ScrollEnd();
7773 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7774 gfx::Point(), InputHandler::GESTURE));
7776 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7777 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7781 TEST_F(LayerTreeHostImplVirtualViewportTest,
7782 TouchFlingCanLockToViewportLayerAfterBubbling) {
7783 gfx::Size content_size = gfx::Size(100, 160);
7784 gfx::Size outer_viewport = gfx::Size(50, 80);
7785 gfx::Size inner_viewport = gfx::Size(25, 40);
7787 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7789 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7790 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7792 scoped_ptr<LayerImpl> child =
7793 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7794 LayerImpl* child_scroll = child.get();
7795 outer_scroll->children()[0]->AddChild(child.Pass());
7797 DrawFrame();
7799 scoped_ptr<ScrollAndScaleSet> scroll_info;
7801 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7802 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7803 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7804 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7805 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7806 InputHandler::GESTURE));
7808 // The child should have scrolled up to its limit.
7809 scroll_info = host_impl_->ProcessScrollDeltas();
7810 ASSERT_EQ(1u, scroll_info->scrolls.size());
7811 EXPECT_TRUE(
7812 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7813 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7815 // The first |ScrollBy| after the fling should re-lock the scrolling
7816 // layer to the first layer that scrolled, the inner viewport scroll layer.
7817 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7818 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7819 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7820 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7821 InputHandler::GESTURE));
7823 // The inner viewport should have scrolled up to its limit.
7824 scroll_info = host_impl_->ProcessScrollDeltas();
7825 ASSERT_EQ(2u, scroll_info->scrolls.size());
7826 EXPECT_TRUE(
7827 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7828 EXPECT_TRUE(
7829 ScrollInfoContains(*scroll_info, inner_scroll->id(), scroll_delta));
7831 // As the locked layer is at its limit, no further scrolling can occur.
7832 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7833 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7834 host_impl_->ScrollEnd();
7835 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7836 gfx::Point(), InputHandler::GESTURE));
7840 TEST_F(LayerTreeHostImplVirtualViewportTest,
7841 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest) {
7842 gfx::Size content_size = gfx::Size(100, 160);
7843 gfx::Size outer_viewport = gfx::Size(50, 80);
7844 gfx::Size inner_viewport = gfx::Size(25, 40);
7846 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7848 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7849 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7851 scoped_ptr<LayerImpl> child =
7852 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7853 LayerImpl* child_scroll = child.get();
7854 outer_scroll->children()[0]->AddChild(child.Pass());
7856 DrawFrame();
7858 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7859 host_impl_->RootScrollBegin(InputHandler::GESTURE));
7860 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7861 host_impl_->ScrollEnd();
7862 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7863 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7864 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7865 host_impl_->ScrollEnd();
7868 TEST_F(LayerTreeHostImplVirtualViewportTest,
7869 NoOverscrollWhenInnerViewportCantScroll) {
7870 InputHandlerScrollResult scroll_result;
7871 gfx::Size content_size = gfx::Size(100, 160);
7872 gfx::Size outer_viewport = gfx::Size(50, 80);
7873 gfx::Size inner_viewport = gfx::Size(25, 40);
7874 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7875 DrawFrame();
7877 // Make inner viewport unscrollable.
7878 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7879 inner_scroll->set_user_scrollable_horizontal(false);
7880 inner_scroll->set_user_scrollable_vertical(false);
7882 // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
7883 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
7884 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7885 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7886 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
7887 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
7889 // When inner viewport is unscrollable, a fling gives zero overscroll.
7890 EXPECT_FALSE(scroll_result.did_overscroll_root);
7891 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
7894 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7895 public:
7896 void SetUp() override {
7897 LayerTreeSettings settings = DefaultSettings();
7898 settings.max_memory_for_prepaint_percentage = 50;
7899 CreateHostImpl(settings, CreateOutputSurface());
7903 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7904 // Set up a memory policy and percentages which could cause
7905 // 32-bit integer overflows.
7906 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7908 // Verify implicit limits are calculated correctly with no overflows
7909 host_impl_->SetMemoryPolicy(mem_policy);
7910 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7911 300u * 1024u * 1024u);
7912 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7913 150u * 1024u * 1024u);
7916 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7917 const gfx::Size layer_size(100, 100);
7918 gfx::Transform external_transform;
7919 const gfx::Rect external_viewport(layer_size);
7920 const gfx::Rect external_clip(layer_size);
7921 const bool resourceless_software_draw = false;
7922 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7924 host_impl_->SetExternalDrawConstraints(external_transform,
7925 external_viewport,
7926 external_clip,
7927 external_viewport,
7928 external_transform,
7929 resourceless_software_draw);
7930 DrawFrame();
7931 EXPECT_TRANSFORMATION_MATRIX_EQ(
7932 external_transform, layer->draw_properties().target_space_transform);
7934 external_transform.Translate(20, 20);
7935 host_impl_->SetExternalDrawConstraints(external_transform,
7936 external_viewport,
7937 external_clip,
7938 external_viewport,
7939 external_transform,
7940 resourceless_software_draw);
7941 DrawFrame();
7942 EXPECT_TRANSFORMATION_MATRIX_EQ(
7943 external_transform, layer->draw_properties().target_space_transform);
7946 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
7947 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7948 DrawFrame();
7950 base::TimeTicks start_time =
7951 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7953 BeginFrameArgs begin_frame_args =
7954 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
7956 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7957 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7959 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7961 begin_frame_args.frame_time = start_time;
7962 host_impl_->WillBeginImplFrame(begin_frame_args);
7963 host_impl_->Animate();
7964 host_impl_->UpdateAnimationState(true);
7966 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
7967 host_impl_->DidFinishImplFrame();
7969 begin_frame_args.frame_time =
7970 start_time + base::TimeDelta::FromMilliseconds(50);
7971 host_impl_->WillBeginImplFrame(begin_frame_args);
7972 host_impl_->Animate();
7973 host_impl_->UpdateAnimationState(true);
7975 float y = scrolling_layer->CurrentScrollOffset().y();
7976 EXPECT_TRUE(y > 1 && y < 49);
7978 // Update target.
7979 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7980 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7981 host_impl_->DidFinishImplFrame();
7983 begin_frame_args.frame_time =
7984 start_time + base::TimeDelta::FromMilliseconds(200);
7985 host_impl_->WillBeginImplFrame(begin_frame_args);
7986 host_impl_->Animate();
7987 host_impl_->UpdateAnimationState(true);
7989 y = scrolling_layer->CurrentScrollOffset().y();
7990 EXPECT_TRUE(y > 50 && y < 100);
7991 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7992 host_impl_->DidFinishImplFrame();
7994 begin_frame_args.frame_time =
7995 start_time + base::TimeDelta::FromMilliseconds(250);
7996 host_impl_->WillBeginImplFrame(begin_frame_args);
7997 host_impl_->Animate();
7998 host_impl_->UpdateAnimationState(true);
8000 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8001 scrolling_layer->CurrentScrollOffset());
8002 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
8003 host_impl_->DidFinishImplFrame();
8006 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
8007 TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
8008 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8009 DrawFrame();
8011 base::TimeTicks start_time =
8012 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8014 BeginFrameArgs begin_frame_args =
8015 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8017 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8018 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8020 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
8022 begin_frame_args.frame_time = start_time;
8023 host_impl_->WillBeginImplFrame(begin_frame_args);
8024 host_impl_->Animate();
8025 host_impl_->UpdateAnimationState(true);
8027 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
8028 host_impl_->DidFinishImplFrame();
8030 begin_frame_args.frame_time =
8031 start_time + base::TimeDelta::FromMilliseconds(50);
8032 host_impl_->WillBeginImplFrame(begin_frame_args);
8033 host_impl_->Animate();
8034 host_impl_->UpdateAnimationState(true);
8036 float y = scrolling_layer->CurrentScrollOffset().y();
8037 EXPECT_TRUE(y > 1 && y < 49);
8039 // Update target.
8040 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8041 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8042 host_impl_->DidFinishImplFrame();
8044 begin_frame_args.frame_time =
8045 start_time + base::TimeDelta::FromMilliseconds(200);
8046 host_impl_->WillBeginImplFrame(begin_frame_args);
8047 host_impl_->Animate();
8048 host_impl_->UpdateAnimationState(true);
8050 y = scrolling_layer->CurrentScrollOffset().y();
8051 EXPECT_TRUE(y > 50 && y < 100);
8052 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
8053 host_impl_->DidFinishImplFrame();
8055 begin_frame_args.frame_time =
8056 start_time + base::TimeDelta::FromMilliseconds(250);
8057 host_impl_->WillBeginImplFrame(begin_frame_args);
8058 host_impl_->Animate();
8059 host_impl_->UpdateAnimationState(true);
8061 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8062 scrolling_layer->CurrentScrollOffset());
8063 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
8064 host_impl_->DidFinishImplFrame();
8067 TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) {
8068 host_impl_->CreatePendingTree();
8070 Region empty_invalidation;
8071 scoped_refptr<RasterSource> pile_with_tiles(
8072 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
8073 gfx::Size(10, 10)));
8075 scoped_ptr<FakePictureLayerImpl> layer =
8076 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11);
8077 layer->SetBounds(gfx::Size(10, 10));
8078 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
8079 layer->SetDrawsContent(true);
8080 layer->tilings()->AddTiling(1.0f, pile_with_tiles);
8081 layer->UpdateRasterSource(pile_with_tiles, &empty_invalidation, nullptr);
8082 layer->tilings()->tiling_at(0)->set_resolution(
8083 TileResolution::HIGH_RESOLUTION);
8084 layer->tilings()->tiling_at(0)->CreateAllTilesForTesting();
8085 layer->tilings()->tiling_at(0)->ComputeTilePriorityRects(
8086 gfx::Rect(gfx::Size(10, 10)), 1.f, 1.0, Occlusion());
8087 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
8089 FakePictureLayerImpl* root_layer = static_cast<FakePictureLayerImpl*>(
8090 host_impl_->pending_tree()->root_layer());
8092 root_layer->set_has_valid_tile_priorities(true);
8093 scoped_ptr<RasterTilePriorityQueue> non_empty_raster_priority_queue_all =
8094 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
8095 RasterTilePriorityQueue::Type::ALL);
8096 EXPECT_FALSE(non_empty_raster_priority_queue_all->IsEmpty());
8098 root_layer->set_has_valid_tile_priorities(false);
8099 scoped_ptr<RasterTilePriorityQueue> empty_raster_priority_queue_all =
8100 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
8101 RasterTilePriorityQueue::Type::ALL);
8102 EXPECT_TRUE(empty_raster_priority_queue_all->IsEmpty());
8105 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
8106 host_impl_->CreatePendingTree();
8107 host_impl_->ActivateSyncTree();
8108 host_impl_->CreatePendingTree();
8110 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
8112 scoped_ptr<FakePictureLayerImpl> pending_layer =
8113 FakePictureLayerImpl::Create(pending_tree, 10);
8114 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
8115 pending_tree->SetRootLayer(pending_layer.Pass());
8116 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
8118 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
8119 pending_tree->DidBecomeActive();
8120 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
8122 scoped_ptr<FakePictureLayerImpl> mask_layer =
8123 FakePictureLayerImpl::Create(pending_tree, 11);
8124 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
8125 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
8126 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
8128 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
8129 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
8130 pending_tree->DidBecomeActive();
8131 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
8132 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
8134 scoped_ptr<FakePictureLayerImpl> replica_layer =
8135 FakePictureLayerImpl::Create(pending_tree, 12);
8136 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
8137 FakePictureLayerImpl::Create(pending_tree, 13);
8138 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
8139 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
8140 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
8141 ASSERT_EQ(raw_replica_mask_layer,
8142 raw_pending_layer->replica_layer()->mask_layer());
8144 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
8145 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
8146 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
8147 pending_tree->DidBecomeActive();
8148 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
8149 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
8150 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
8153 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
8154 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
8155 host_impl_->SetViewportSize(gfx::Size(50, 50));
8156 DrawFrame();
8158 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
8160 float min_page_scale = 1.f, max_page_scale = 4.f;
8161 float page_scale_factor = 1.f;
8163 // The scroll deltas should have the page scale factor applied.
8165 host_impl_->active_tree()->PushPageScaleFromMainThread(
8166 page_scale_factor, min_page_scale, max_page_scale);
8167 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
8168 scroll_layer->SetScrollDelta(gfx::Vector2d());
8170 float page_scale_delta = 2.f;
8171 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
8172 host_impl_->PinchGestureBegin();
8173 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
8174 host_impl_->PinchGestureEnd();
8175 host_impl_->ScrollEnd();
8177 gfx::Vector2dF scroll_delta(0, 5);
8178 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8179 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
8180 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
8182 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
8183 host_impl_->ScrollEnd();
8184 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8185 scroll_layer->CurrentScrollOffset());
8189 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
8190 public:
8191 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8192 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
8194 protected:
8195 int num_lost_surfaces_;
8198 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
8199 // Really we just need at least one client notification each time
8200 // we go from having a valid output surface to not having a valid output
8201 // surface.
8202 EXPECT_EQ(0, num_lost_surfaces_);
8203 host_impl_->DidLoseOutputSurface();
8204 EXPECT_EQ(1, num_lost_surfaces_);
8205 host_impl_->DidLoseOutputSurface();
8206 EXPECT_LE(1, num_lost_surfaces_);
8209 TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) {
8210 LayerTreeHostImpl::FrameData frame;
8211 frame.render_passes.push_back(RenderPass::Create());
8212 RenderPass* pass3 = frame.render_passes.back();
8213 frame.render_passes.push_back(RenderPass::Create());
8214 RenderPass* pass2 = frame.render_passes.back();
8215 frame.render_passes.push_back(RenderPass::Create());
8216 RenderPass* pass1 = frame.render_passes.back();
8218 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8219 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8220 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8222 frame.render_passes_by_id[pass1->id] = pass1;
8223 frame.render_passes_by_id[pass2->id] = pass2;
8224 frame.render_passes_by_id[pass3->id] = pass3;
8226 // Add a quad to each pass so they aren't empty.
8227 SolidColorDrawQuad* color_quad;
8228 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8229 color_quad->material = DrawQuad::SOLID_COLOR;
8230 color_quad = pass2->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8231 color_quad->material = DrawQuad::SOLID_COLOR;
8232 color_quad = pass3->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8233 color_quad->material = DrawQuad::SOLID_COLOR;
8235 // pass3 is referenced by pass2.
8236 RenderPassDrawQuad* rpdq =
8237 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8238 rpdq->material = DrawQuad::RENDER_PASS;
8239 rpdq->render_pass_id = pass3->id;
8241 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
8242 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
8243 EXPECT_EQ(1u, frame.render_passes_by_id.size());
8244 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
8245 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
8246 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
8247 EXPECT_EQ(1u, frame.render_passes.size());
8248 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
8251 TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) {
8252 LayerTreeHostImpl::FrameData frame;
8253 frame.render_passes.push_back(RenderPass::Create());
8254 RenderPass* pass3 = frame.render_passes.back();
8255 frame.render_passes.push_back(RenderPass::Create());
8256 RenderPass* pass2 = frame.render_passes.back();
8257 frame.render_passes.push_back(RenderPass::Create());
8258 RenderPass* pass1 = frame.render_passes.back();
8260 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8261 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8262 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8264 frame.render_passes_by_id[pass1->id] = pass1;
8265 frame.render_passes_by_id[pass2->id] = pass2;
8266 frame.render_passes_by_id[pass3->id] = pass3;
8268 // pass1 is not empty, but pass2 and pass3 are.
8269 SolidColorDrawQuad* color_quad;
8270 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8271 color_quad->material = DrawQuad::SOLID_COLOR;
8273 // pass3 is referenced by pass2.
8274 RenderPassDrawQuad* rpdq =
8275 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8276 rpdq->material = DrawQuad::RENDER_PASS;
8277 rpdq->render_pass_id = pass3->id;
8279 // pass2 is referenced by pass1.
8280 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8281 rpdq->material = DrawQuad::RENDER_PASS;
8282 rpdq->render_pass_id = pass2->id;
8284 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8285 // should be removed.
8286 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
8287 EXPECT_EQ(1u, frame.render_passes_by_id.size());
8288 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
8289 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
8290 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
8291 EXPECT_EQ(1u, frame.render_passes.size());
8292 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
8293 // The RenderPassDrawQuad should be removed from pass1.
8294 EXPECT_EQ(1u, pass1->quad_list.size());
8295 EXPECT_EQ(DrawQuad::SOLID_COLOR, pass1->quad_list.ElementAt(0)->material);
8298 TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) {
8299 LayerTreeHostImpl::FrameData frame;
8300 frame.render_passes.push_back(RenderPass::Create());
8301 RenderPass* pass3 = frame.render_passes.back();
8302 frame.render_passes.push_back(RenderPass::Create());
8303 RenderPass* pass2 = frame.render_passes.back();
8304 frame.render_passes.push_back(RenderPass::Create());
8305 RenderPass* pass1 = frame.render_passes.back();
8307 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8308 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8309 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8311 frame.render_passes_by_id[pass1->id] = pass1;
8312 frame.render_passes_by_id[pass2->id] = pass2;
8313 frame.render_passes_by_id[pass3->id] = pass3;
8315 // pass3 is referenced by pass2.
8316 RenderPassDrawQuad* rpdq =
8317 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8318 rpdq->material = DrawQuad::RENDER_PASS;
8319 rpdq->render_pass_id = pass3->id;
8321 // pass2 is referenced by pass1.
8322 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8323 rpdq->material = DrawQuad::RENDER_PASS;
8324 rpdq->render_pass_id = pass2->id;
8326 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8327 // should be removed. Then pass1 is empty too, but it's the root so it should
8328 // not be removed.
8329 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
8330 EXPECT_EQ(1u, frame.render_passes_by_id.size());
8331 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
8332 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
8333 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
8334 EXPECT_EQ(1u, frame.render_passes.size());
8335 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
8336 // The RenderPassDrawQuad should be removed from pass1.
8337 EXPECT_EQ(0u, pass1->quad_list.size());
8340 class FakeVideoFrameController : public VideoFrameController {
8341 public:
8342 void OnBeginFrame(const BeginFrameArgs& args) override {
8343 begin_frame_args_ = args;
8344 did_draw_frame_ = false;
8347 void DidDrawFrame() override { did_draw_frame_ = true; }
8349 const BeginFrameArgs& begin_frame_args() const { return begin_frame_args_; }
8351 bool did_draw_frame() const { return did_draw_frame_; }
8353 private:
8354 BeginFrameArgs begin_frame_args_;
8355 bool did_draw_frame_ = false;
8358 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
8359 BeginFrameArgs begin_frame_args =
8360 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8361 FakeVideoFrameController controller;
8363 host_impl_->WillBeginImplFrame(begin_frame_args);
8364 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8365 host_impl_->AddVideoFrameController(&controller);
8366 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8367 host_impl_->DidFinishImplFrame();
8369 EXPECT_FALSE(controller.did_draw_frame());
8370 LayerTreeHostImpl::FrameData frame;
8371 host_impl_->DidDrawAllLayers(frame);
8372 EXPECT_TRUE(controller.did_draw_frame());
8374 controller.OnBeginFrame(begin_frame_args);
8375 EXPECT_FALSE(controller.did_draw_frame());
8376 host_impl_->RemoveVideoFrameController(&controller);
8377 host_impl_->DidDrawAllLayers(frame);
8378 EXPECT_FALSE(controller.did_draw_frame());
8381 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) {
8382 BeginFrameArgs begin_frame_args =
8383 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8384 FakeVideoFrameController controller;
8386 host_impl_->WillBeginImplFrame(begin_frame_args);
8387 host_impl_->DidFinishImplFrame();
8389 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8390 host_impl_->AddVideoFrameController(&controller);
8391 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8393 begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8394 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8395 host_impl_->WillBeginImplFrame(begin_frame_args);
8396 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8398 EXPECT_FALSE(controller.did_draw_frame());
8399 LayerTreeHostImpl::FrameData frame;
8400 host_impl_->DidDrawAllLayers(frame);
8401 EXPECT_TRUE(controller.did_draw_frame());
8403 controller.OnBeginFrame(begin_frame_args);
8404 EXPECT_FALSE(controller.did_draw_frame());
8405 host_impl_->RemoveVideoFrameController(&controller);
8406 host_impl_->DidDrawAllLayers(frame);
8407 EXPECT_FALSE(controller.did_draw_frame());
8410 TEST_F(LayerTreeHostImplTest, GpuRasterizationStatusModes) {
8411 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8413 host_impl_->SetHasGpuRasterizationTrigger(true);
8414 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8415 EXPECT_EQ(GpuRasterizationStatus::ON, host_impl_->gpu_rasterization_status());
8416 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8418 host_impl_->SetHasGpuRasterizationTrigger(false);
8419 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8420 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT,
8421 host_impl_->gpu_rasterization_status());
8422 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8424 host_impl_->SetHasGpuRasterizationTrigger(true);
8425 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8426 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT,
8427 host_impl_->gpu_rasterization_status());
8428 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8429 EXPECT_FALSE(host_impl_->use_msaa());
8431 scoped_ptr<TestWebGraphicsContext3D> context_with_msaa =
8432 TestWebGraphicsContext3D::Create();
8433 context_with_msaa->SetMaxSamples(8);
8435 LayerTreeSettings msaaSettings = GpuRasterizationEnabledSettings();
8436 msaaSettings.gpu_rasterization_msaa_sample_count = 4;
8437 EXPECT_TRUE(CreateHostImpl(
8438 msaaSettings, FakeOutputSurface::Create3d(context_with_msaa.Pass())));
8439 host_impl_->SetHasGpuRasterizationTrigger(true);
8440 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8441 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT,
8442 host_impl_->gpu_rasterization_status());
8443 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8444 EXPECT_TRUE(host_impl_->use_msaa());
8446 LayerTreeSettings settings = DefaultSettings();
8447 settings.gpu_rasterization_enabled = false;
8448 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8449 host_impl_->SetHasGpuRasterizationTrigger(true);
8450 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8451 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE,
8452 host_impl_->gpu_rasterization_status());
8453 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8455 settings.gpu_rasterization_forced = true;
8456 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8458 host_impl_->SetHasGpuRasterizationTrigger(false);
8459 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8460 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED,
8461 host_impl_->gpu_rasterization_status());
8462 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8465 // A mock output surface which lets us detect calls to ForceReclaimResources.
8466 class MockReclaimResourcesOutputSurface : public FakeOutputSurface {
8467 public:
8468 static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() {
8469 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8470 TestContextProvider::Create(), TestContextProvider::Create(), false));
8473 MOCK_METHOD0(ForceReclaimResources, void());
8475 protected:
8476 MockReclaimResourcesOutputSurface(
8477 scoped_refptr<ContextProvider> context_provider,
8478 scoped_refptr<ContextProvider> worker_context_provider,
8479 bool delegated_rendering)
8480 : FakeOutputSurface(context_provider,
8481 worker_context_provider,
8482 delegated_rendering) {}
8485 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8486 // being reclaimed to block drawing between BeginCommit / Swap. This test
8487 // ensures that BeginCommit triggers ForceReclaimResources. See
8488 // crbug.com/489515.
8489 TEST_F(LayerTreeHostImplTest, BeginCommitReclaimsResources) {
8490 scoped_ptr<MockReclaimResourcesOutputSurface> output_surface(
8491 MockReclaimResourcesOutputSurface::Create3d());
8492 // Hold an unowned pointer to the output surface to use for mock expectations.
8493 MockReclaimResourcesOutputSurface* mock_output_surface = output_surface.get();
8495 CreateHostImpl(DefaultSettings(), output_surface.Pass());
8496 EXPECT_CALL(*mock_output_surface, ForceReclaimResources()).Times(1);
8497 host_impl_->BeginCommit();
8500 } // namespace
8501 } // namespace cc