This sets up API to release OutputSurface from LTHClient.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blobeeaf88f2b8dbdce2b1a07cf58cfdf30de7b614b9
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_->active_tree()->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_->active_tree()->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 CreateHostImpl(settings,
1239 CreateOutputSurface());
1240 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.25f, 4.f);
1242 const gfx::Size content_size(1000, 1000);
1243 const gfx::Size viewport_size(500, 500);
1244 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1246 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1247 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1249 EXPECT_VECTOR_EQ(
1250 gfx::Vector2dF(500, 500),
1251 outer_scroll_layer->MaxScrollOffset());
1253 host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
1254 host_impl_->PinchGestureBegin();
1255 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1256 host_impl_->PinchGestureEnd();
1257 host_impl_->ScrollEnd();
1259 // Sanity check - we're zoomed in, starting from the origin.
1260 EXPECT_VECTOR_EQ(
1261 gfx::Vector2dF(0, 0),
1262 outer_scroll_layer->CurrentScrollOffset());
1263 EXPECT_VECTOR_EQ(
1264 gfx::Vector2dF(0, 0),
1265 inner_scroll_layer->CurrentScrollOffset());
1267 // Scroll down - only the inner viewport should scroll.
1268 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1269 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f));
1270 host_impl_->ScrollEnd();
1272 EXPECT_VECTOR_EQ(
1273 gfx::Vector2dF(50, 50),
1274 inner_scroll_layer->CurrentScrollOffset());
1275 EXPECT_VECTOR_EQ(
1276 gfx::Vector2dF(0, 0),
1277 outer_scroll_layer->CurrentScrollOffset());
1279 // Scroll down - outer viewport should start scrolling after the inner is at
1280 // its maximum.
1281 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1282 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f, 1000.f));
1283 host_impl_->ScrollEnd();
1285 EXPECT_VECTOR_EQ(
1286 gfx::Vector2dF(250, 250),
1287 inner_scroll_layer->CurrentScrollOffset());
1288 EXPECT_VECTOR_EQ(
1289 gfx::Vector2dF(300, 300),
1290 outer_scroll_layer->CurrentScrollOffset());
1293 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1294 // as expected. That is, scrolling during a pinch should bubble from the inner
1295 // to the outer viewport.
1296 TEST_F(LayerTreeHostImplTest, ScrollDuringPinchGesture) {
1297 LayerTreeSettings settings = DefaultSettings();
1298 CreateHostImpl(settings,
1299 CreateOutputSurface());
1300 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
1302 const gfx::Size content_size(1000, 1000);
1303 const gfx::Size viewport_size(500, 500);
1304 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1306 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1307 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1309 EXPECT_VECTOR_EQ(
1310 gfx::Vector2dF(500, 500),
1311 outer_scroll_layer->MaxScrollOffset());
1313 host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
1314 host_impl_->PinchGestureBegin();
1316 host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
1317 EXPECT_VECTOR_EQ(
1318 gfx::Vector2dF(0, 0),
1319 outer_scroll_layer->CurrentScrollOffset());
1320 EXPECT_VECTOR_EQ(
1321 gfx::Vector2dF(125, 125),
1322 inner_scroll_layer->CurrentScrollOffset());
1324 // Needed so that the pinch is accounted for in draw properties.
1325 DrawFrame();
1327 host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f));
1328 EXPECT_VECTOR_EQ(
1329 gfx::Vector2dF(0, 0),
1330 outer_scroll_layer->CurrentScrollOffset());
1331 EXPECT_VECTOR_EQ(
1332 gfx::Vector2dF(130, 130),
1333 inner_scroll_layer->CurrentScrollOffset());
1335 DrawFrame();
1337 host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f, 400.f));
1338 EXPECT_VECTOR_EQ(
1339 gfx::Vector2dF(80, 80),
1340 outer_scroll_layer->CurrentScrollOffset());
1341 EXPECT_VECTOR_EQ(
1342 gfx::Vector2dF(250, 250),
1343 inner_scroll_layer->CurrentScrollOffset());
1345 host_impl_->PinchGestureEnd();
1346 host_impl_->ScrollEnd();
1349 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1350 // a pinch zoom is anchored within a certain margin of the screen edge, we
1351 // should assume the user means to scroll into the edge of the screen.
1352 TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
1353 LayerTreeSettings settings = DefaultSettings();
1354 CreateHostImpl(settings,
1355 CreateOutputSurface());
1356 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
1358 const gfx::Size content_size(1000, 1000);
1359 const gfx::Size viewport_size(500, 500);
1360 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1362 int offsetFromEdge = Viewport::kPinchZoomSnapMarginDips - 5;
1363 gfx::Point anchor(viewport_size.width() - offsetFromEdge,
1364 viewport_size.height() - offsetFromEdge);
1366 // Pinch in within the margins. The scroll should stay exactly locked to the
1367 // bottom and right.
1368 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1369 host_impl_->PinchGestureBegin();
1370 host_impl_->PinchGestureUpdate(2, anchor);
1371 host_impl_->PinchGestureEnd();
1372 host_impl_->ScrollEnd();
1374 EXPECT_VECTOR_EQ(
1375 gfx::Vector2dF(250, 250),
1376 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1378 // Reset.
1379 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1380 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1381 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1383 // Pinch in within the margins. The scroll should stay exactly locked to the
1384 // top and left.
1385 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1386 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1387 host_impl_->PinchGestureBegin();
1388 host_impl_->PinchGestureUpdate(2, anchor);
1389 host_impl_->PinchGestureEnd();
1390 host_impl_->ScrollEnd();
1392 EXPECT_VECTOR_EQ(
1393 gfx::Vector2dF(0, 0),
1394 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1396 // Reset.
1397 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1398 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1399 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1401 // Pinch in just outside the margin. There should be no snapping.
1402 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1403 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1404 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1405 host_impl_->PinchGestureBegin();
1406 host_impl_->PinchGestureUpdate(2, anchor);
1407 host_impl_->PinchGestureEnd();
1408 host_impl_->ScrollEnd();
1410 EXPECT_VECTOR_EQ(
1411 gfx::Vector2dF(50, 50),
1412 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1414 // Reset.
1415 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1416 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1417 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1419 // Pinch in just outside the margin. There should be no snapping.
1420 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1421 anchor = gfx::Point(viewport_size.width() - offsetFromEdge,
1422 viewport_size.height() - offsetFromEdge);
1423 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1424 host_impl_->PinchGestureBegin();
1425 host_impl_->PinchGestureUpdate(2, anchor);
1426 host_impl_->PinchGestureEnd();
1427 host_impl_->ScrollEnd();
1429 EXPECT_VECTOR_EQ(
1430 gfx::Vector2dF(200, 200),
1431 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1434 TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
1435 const gfx::Size content_size(200, 200);
1436 const gfx::Size viewport_size(100, 100);
1437 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1439 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1440 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1442 // Zoom into the page by a 2X factor
1443 float min_page_scale = 1.f, max_page_scale = 4.f;
1444 float page_scale_factor = 2.f;
1445 host_impl_->active_tree()->PushPageScaleFromMainThread(
1446 page_scale_factor, min_page_scale, max_page_scale);
1447 host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
1449 // Scroll by a small amount, there should be no bubbling to the outer
1450 // viewport.
1451 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1452 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f));
1453 host_impl_->ScrollEnd();
1455 EXPECT_VECTOR_EQ(
1456 gfx::Vector2dF(5, 10),
1457 inner_scroll_layer->CurrentScrollOffset());
1458 EXPECT_VECTOR_EQ(
1459 gfx::Vector2dF(),
1460 outer_scroll_layer->CurrentScrollOffset());
1462 // Scroll by the inner viewport's max scroll extent, the remainder
1463 // should bubble up to the outer viewport.
1464 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1465 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f));
1466 host_impl_->ScrollEnd();
1468 EXPECT_VECTOR_EQ(
1469 gfx::Vector2dF(50, 50),
1470 inner_scroll_layer->CurrentScrollOffset());
1471 EXPECT_VECTOR_EQ(
1472 gfx::Vector2dF(5, 10),
1473 outer_scroll_layer->CurrentScrollOffset());
1475 // Scroll by the outer viewport's max scroll extent, it should all go to the
1476 // outer viewport.
1477 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1478 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(190.f, 180.f));
1479 host_impl_->ScrollEnd();
1481 EXPECT_VECTOR_EQ(
1482 gfx::Vector2dF(100, 100),
1483 outer_scroll_layer->CurrentScrollOffset());
1484 EXPECT_VECTOR_EQ(
1485 gfx::Vector2dF(50, 50),
1486 inner_scroll_layer->CurrentScrollOffset());
1489 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
1490 ui::LatencyInfo latency_info;
1491 latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
1492 1234);
1493 scoped_ptr<SwapPromise> swap_promise(
1494 new LatencyInfoSwapPromise(latency_info));
1496 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1497 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1498 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
1499 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1500 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
1501 host_impl_->ScrollEnd();
1503 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1504 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1505 EXPECT_EQ(latency_info.trace_id(), scroll_info->swap_promises[0]->TraceId());
1508 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1509 // up to the scroll_parent, rather than the stacking parent.
1510 TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
1511 LayerImpl* viewport_scroll =
1512 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1513 host_impl_->SetViewportSize(gfx::Size(50, 50));
1515 // Set up two scrolling children of the root, one of which is a scroll parent
1516 // to the other. Scrolls bubbling from the child should bubble to the parent,
1517 // not the viewport.
1518 LayerImpl *parent;
1519 LayerImpl *child;
1520 LayerImpl *child_clip;
1522 scoped_ptr<LayerImpl> scroll_parent_clip =
1523 LayerImpl::Create(host_impl_->active_tree(), 6);
1524 scoped_ptr<LayerImpl> scroll_parent = CreateScrollableLayer(
1525 7, gfx::Size(10, 10), scroll_parent_clip.get());
1526 parent = scroll_parent.get();
1527 scroll_parent_clip->AddChild(scroll_parent.Pass());
1529 viewport_scroll->AddChild(scroll_parent_clip.Pass());
1531 scoped_ptr<LayerImpl> scroll_child_clip =
1532 LayerImpl::Create(host_impl_->active_tree(), 8);
1533 scoped_ptr<LayerImpl> scroll_child = CreateScrollableLayer(
1534 9, gfx::Size(10, 10), scroll_child_clip.get());
1535 child = scroll_child.get();
1536 scroll_child->SetPosition(gfx::Point(20, 20));
1537 scroll_child_clip->AddChild(scroll_child.Pass());
1539 child_clip = scroll_child_clip.get();
1540 viewport_scroll->AddChild(scroll_child_clip.Pass());
1542 child_clip->SetScrollParent(parent);
1544 DrawFrame();
1547 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1548 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1549 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1550 host_impl_->ScrollEnd();
1552 // The child should be fully scrolled by the first ScrollBy.
1553 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child->CurrentScrollOffset());
1555 // The scroll_parent should receive the bubbled up second ScrollBy.
1556 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent->CurrentScrollOffset());
1558 // The viewport shouldn't have been scrolled at all.
1559 EXPECT_VECTOR_EQ(
1560 gfx::Vector2dF(0, 0),
1561 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1562 EXPECT_VECTOR_EQ(
1563 gfx::Vector2dF(0, 0),
1564 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1568 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1569 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1570 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1571 host_impl_->ScrollEnd();
1573 // The first ScrollBy should scroll the parent to its extent.
1574 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent->CurrentScrollOffset());
1576 // The viewport should now be next in bubbling order.
1577 EXPECT_VECTOR_EQ(
1578 gfx::Vector2dF(2, 1),
1579 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1580 EXPECT_VECTOR_EQ(
1581 gfx::Vector2dF(0, 0),
1582 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1587 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1588 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1589 host_impl_->SetViewportSize(gfx::Size(50, 50));
1590 DrawFrame();
1592 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1593 DCHECK(scroll_layer);
1595 float min_page_scale = 1.f;
1596 float max_page_scale = 4.f;
1598 // Basic pinch zoom in gesture
1600 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1601 max_page_scale);
1602 scroll_layer->SetScrollDelta(gfx::Vector2d());
1604 float page_scale_delta = 2.f;
1605 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1606 host_impl_->PinchGestureBegin();
1607 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1608 host_impl_->PinchGestureEnd();
1609 host_impl_->ScrollEnd();
1610 EXPECT_FALSE(did_request_animate_);
1611 EXPECT_TRUE(did_request_redraw_);
1612 EXPECT_TRUE(did_request_commit_);
1614 scoped_ptr<ScrollAndScaleSet> scroll_info =
1615 host_impl_->ProcessScrollDeltas();
1616 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1619 // Zoom-in clamping
1621 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1622 max_page_scale);
1623 scroll_layer->SetScrollDelta(gfx::Vector2d());
1624 float page_scale_delta = 10.f;
1626 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1627 host_impl_->PinchGestureBegin();
1628 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1629 host_impl_->PinchGestureEnd();
1630 host_impl_->ScrollEnd();
1632 scoped_ptr<ScrollAndScaleSet> scroll_info =
1633 host_impl_->ProcessScrollDeltas();
1634 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1637 // Zoom-out clamping
1639 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1640 max_page_scale);
1641 scroll_layer->SetScrollDelta(gfx::Vector2d());
1642 scroll_layer->PullDeltaForMainThread();
1643 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1645 float page_scale_delta = 0.1f;
1646 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1647 host_impl_->PinchGestureBegin();
1648 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1649 host_impl_->PinchGestureEnd();
1650 host_impl_->ScrollEnd();
1652 scoped_ptr<ScrollAndScaleSet> scroll_info =
1653 host_impl_->ProcessScrollDeltas();
1654 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1656 EXPECT_TRUE(scroll_info->scrolls.empty());
1659 // Two-finger panning should not happen based on pinch events only
1661 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1662 max_page_scale);
1663 scroll_layer->SetScrollDelta(gfx::Vector2d());
1664 scroll_layer->PullDeltaForMainThread();
1665 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1667 float page_scale_delta = 1.f;
1668 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1669 host_impl_->PinchGestureBegin();
1670 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1671 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1672 host_impl_->PinchGestureEnd();
1673 host_impl_->ScrollEnd();
1675 scoped_ptr<ScrollAndScaleSet> scroll_info =
1676 host_impl_->ProcessScrollDeltas();
1677 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1678 EXPECT_TRUE(scroll_info->scrolls.empty());
1681 // Two-finger panning should work with interleaved scroll events
1683 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1684 max_page_scale);
1685 scroll_layer->SetScrollDelta(gfx::Vector2d());
1686 scroll_layer->PullDeltaForMainThread();
1687 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1689 float page_scale_delta = 1.f;
1690 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1691 host_impl_->PinchGestureBegin();
1692 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1693 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1694 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1695 host_impl_->PinchGestureEnd();
1696 host_impl_->ScrollEnd();
1698 scoped_ptr<ScrollAndScaleSet> scroll_info =
1699 host_impl_->ProcessScrollDeltas();
1700 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1701 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1702 gfx::Vector2d(-10, -10)));
1705 // Two-finger panning should work when starting fully zoomed out.
1707 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1708 scroll_layer->SetScrollDelta(gfx::Vector2d());
1709 scroll_layer->PullDeltaForMainThread();
1710 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1712 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1713 host_impl_->PinchGestureBegin();
1714 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1715 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1717 // Needed so layer transform includes page scale.
1718 DrawFrame();
1720 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1721 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1722 host_impl_->PinchGestureEnd();
1723 host_impl_->ScrollEnd();
1725 scoped_ptr<ScrollAndScaleSet> scroll_info =
1726 host_impl_->ProcessScrollDeltas();
1727 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1728 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1729 gfx::Vector2d(10, 10)));
1733 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1734 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1735 host_impl_->SetViewportSize(gfx::Size(50, 50));
1736 DrawFrame();
1738 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1739 DCHECK(scroll_layer);
1741 float min_page_scale = 0.5f;
1742 float max_page_scale = 4.f;
1743 base::TimeTicks start_time = base::TimeTicks() +
1744 base::TimeDelta::FromSeconds(1);
1745 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1746 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1747 base::TimeTicks end_time = start_time + duration;
1749 BeginFrameArgs begin_frame_args =
1750 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
1752 // Non-anchor zoom-in
1754 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1755 max_page_scale);
1756 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1758 did_request_redraw_ = false;
1759 did_request_animate_ = false;
1760 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1761 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1762 gfx::Vector2d(),
1763 false,
1764 2.f,
1765 duration)));
1766 host_impl_->ActivateSyncTree();
1767 EXPECT_FALSE(did_request_redraw_);
1768 EXPECT_TRUE(did_request_animate_);
1770 did_request_redraw_ = false;
1771 did_request_animate_ = false;
1772 begin_frame_args.frame_time = start_time;
1773 host_impl_->WillBeginImplFrame(begin_frame_args);
1774 host_impl_->Animate();
1775 EXPECT_TRUE(did_request_redraw_);
1776 EXPECT_TRUE(did_request_animate_);
1777 host_impl_->DidFinishImplFrame();
1779 did_request_redraw_ = false;
1780 did_request_animate_ = false;
1781 begin_frame_args.frame_time = halfway_through_animation;
1782 host_impl_->WillBeginImplFrame(begin_frame_args);
1783 host_impl_->Animate();
1784 EXPECT_TRUE(did_request_redraw_);
1785 EXPECT_TRUE(did_request_animate_);
1786 host_impl_->DidFinishImplFrame();
1788 did_request_redraw_ = false;
1789 did_request_animate_ = false;
1790 did_request_commit_ = false;
1791 begin_frame_args.frame_time = end_time;
1792 host_impl_->WillBeginImplFrame(begin_frame_args);
1793 host_impl_->Animate();
1794 EXPECT_TRUE(did_request_commit_);
1795 EXPECT_FALSE(did_request_animate_);
1796 host_impl_->DidFinishImplFrame();
1798 scoped_ptr<ScrollAndScaleSet> scroll_info =
1799 host_impl_->ProcessScrollDeltas();
1800 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1801 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1802 gfx::Vector2d(-50, -50)));
1805 start_time += base::TimeDelta::FromSeconds(10);
1806 halfway_through_animation += base::TimeDelta::FromSeconds(10);
1807 end_time += base::TimeDelta::FromSeconds(10);
1809 // Anchor zoom-out
1811 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1812 max_page_scale);
1813 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1815 did_request_redraw_ = false;
1816 did_request_animate_ = false;
1817 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1818 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1819 gfx::Vector2d(25, 25),
1820 true,
1821 min_page_scale,
1822 duration)));
1823 host_impl_->ActivateSyncTree();
1824 EXPECT_FALSE(did_request_redraw_);
1825 EXPECT_TRUE(did_request_animate_);
1827 did_request_redraw_ = false;
1828 did_request_animate_ = false;
1829 begin_frame_args.frame_time = start_time;
1830 host_impl_->WillBeginImplFrame(begin_frame_args);
1831 host_impl_->Animate();
1832 EXPECT_TRUE(did_request_redraw_);
1833 EXPECT_TRUE(did_request_animate_);
1834 host_impl_->DidFinishImplFrame();
1836 did_request_redraw_ = false;
1837 did_request_commit_ = false;
1838 did_request_animate_ = false;
1839 begin_frame_args.frame_time = end_time;
1840 host_impl_->WillBeginImplFrame(begin_frame_args);
1841 host_impl_->Animate();
1842 EXPECT_TRUE(did_request_redraw_);
1843 EXPECT_FALSE(did_request_animate_);
1844 EXPECT_TRUE(did_request_commit_);
1845 host_impl_->DidFinishImplFrame();
1847 scoped_ptr<ScrollAndScaleSet> scroll_info =
1848 host_impl_->ProcessScrollDeltas();
1849 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1850 // Pushed to (0,0) via clamping against contents layer size.
1851 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1852 gfx::Vector2d(-50, -50)));
1856 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1857 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1858 host_impl_->SetViewportSize(gfx::Size(50, 50));
1859 DrawFrame();
1861 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1862 DCHECK(scroll_layer);
1864 float min_page_scale = 0.5f;
1865 float max_page_scale = 4.f;
1866 base::TimeTicks start_time = base::TimeTicks() +
1867 base::TimeDelta::FromSeconds(1);
1868 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1869 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1870 base::TimeTicks end_time = start_time + duration;
1872 BeginFrameArgs begin_frame_args =
1873 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
1875 // Anchor zoom with unchanged page scale should not change scroll or scale.
1877 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1878 max_page_scale);
1879 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1881 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1882 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1883 gfx::Vector2d(),
1884 true,
1885 1.f,
1886 duration)));
1887 host_impl_->ActivateSyncTree();
1888 begin_frame_args.frame_time = start_time;
1889 host_impl_->WillBeginImplFrame(begin_frame_args);
1890 host_impl_->Animate();
1891 host_impl_->DidFinishImplFrame();
1893 begin_frame_args.frame_time = halfway_through_animation;
1894 host_impl_->WillBeginImplFrame(begin_frame_args);
1895 host_impl_->Animate();
1896 EXPECT_TRUE(did_request_redraw_);
1897 host_impl_->DidFinishImplFrame();
1899 begin_frame_args.frame_time = end_time;
1900 host_impl_->WillBeginImplFrame(begin_frame_args);
1901 host_impl_->Animate();
1902 EXPECT_TRUE(did_request_commit_);
1903 host_impl_->DidFinishImplFrame();
1905 scoped_ptr<ScrollAndScaleSet> scroll_info =
1906 host_impl_->ProcessScrollDeltas();
1907 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1908 ExpectNone(*scroll_info, scroll_layer->id());
1912 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1913 host_impl_->CreatePendingTree();
1914 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
1915 CreateScrollAndContentsLayers(
1916 host_impl_->pending_tree(),
1917 gfx::Size(100, 100));
1918 host_impl_->ActivateSyncTree();
1919 DrawFrame();
1921 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1922 DCHECK(scroll_layer);
1924 float min_page_scale = 0.5f;
1925 float max_page_scale = 4.f;
1926 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1927 max_page_scale);
1928 host_impl_->ActivateSyncTree();
1930 base::TimeTicks start_time = base::TimeTicks() +
1931 base::TimeDelta::FromSeconds(1);
1932 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1933 base::TimeTicks third_through_animation = start_time + duration / 3;
1934 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1935 base::TimeTicks end_time = start_time + duration;
1936 float target_scale = 2.f;
1938 BeginFrameArgs begin_frame_args =
1939 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
1941 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1943 // Make sure TakePageScaleAnimation works properly.
1945 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1946 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1947 gfx::Vector2d(),
1948 false,
1949 target_scale,
1950 duration)));
1951 scoped_ptr<PendingPageScaleAnimation> psa =
1952 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1953 EXPECT_EQ(target_scale, psa->scale);
1954 EXPECT_EQ(duration, psa->duration);
1955 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1957 // Recreate the PSA. Nothing should happen here since the tree containing the
1958 // PSA hasn't been activated yet.
1959 did_request_redraw_ = false;
1960 did_request_animate_ = false;
1961 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1962 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1963 gfx::Vector2d(),
1964 false,
1965 target_scale,
1966 duration)));
1967 begin_frame_args.frame_time = halfway_through_animation;
1968 host_impl_->WillBeginImplFrame(begin_frame_args);
1969 host_impl_->Animate();
1970 EXPECT_FALSE(did_request_animate_);
1971 EXPECT_FALSE(did_request_redraw_);
1972 host_impl_->DidFinishImplFrame();
1974 // Activate the sync tree. This should cause the animation to become enabled.
1975 // It should also clear the pointer on the sync tree.
1976 host_impl_->ActivateSyncTree();
1977 EXPECT_EQ(nullptr,
1978 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1979 EXPECT_FALSE(did_request_redraw_);
1980 EXPECT_TRUE(did_request_animate_);
1982 start_time += base::TimeDelta::FromSeconds(10);
1983 third_through_animation += base::TimeDelta::FromSeconds(10);
1984 halfway_through_animation += base::TimeDelta::FromSeconds(10);
1985 end_time += base::TimeDelta::FromSeconds(10);
1987 // From here on, make sure the animation runs as normal.
1988 did_request_redraw_ = false;
1989 did_request_animate_ = false;
1990 begin_frame_args.frame_time = start_time;
1991 host_impl_->WillBeginImplFrame(begin_frame_args);
1992 host_impl_->Animate();
1993 EXPECT_TRUE(did_request_redraw_);
1994 EXPECT_TRUE(did_request_animate_);
1995 host_impl_->DidFinishImplFrame();
1997 did_request_redraw_ = false;
1998 did_request_animate_ = false;
1999 begin_frame_args.frame_time = third_through_animation;
2000 host_impl_->WillBeginImplFrame(begin_frame_args);
2001 host_impl_->Animate();
2002 EXPECT_TRUE(did_request_redraw_);
2003 EXPECT_TRUE(did_request_animate_);
2004 host_impl_->DidFinishImplFrame();
2006 // Another activation shouldn't have any effect on the animation.
2007 host_impl_->ActivateSyncTree();
2009 did_request_redraw_ = false;
2010 did_request_animate_ = false;
2011 begin_frame_args.frame_time = halfway_through_animation;
2012 host_impl_->WillBeginImplFrame(begin_frame_args);
2013 host_impl_->Animate();
2014 EXPECT_TRUE(did_request_redraw_);
2015 EXPECT_TRUE(did_request_animate_);
2016 host_impl_->DidFinishImplFrame();
2018 did_request_redraw_ = false;
2019 did_request_animate_ = false;
2020 did_request_commit_ = false;
2021 begin_frame_args.frame_time = end_time;
2022 host_impl_->WillBeginImplFrame(begin_frame_args);
2023 host_impl_->Animate();
2024 EXPECT_TRUE(did_request_commit_);
2025 EXPECT_FALSE(did_request_animate_);
2026 host_impl_->DidFinishImplFrame();
2028 scoped_ptr<ScrollAndScaleSet> scroll_info =
2029 host_impl_->ProcessScrollDeltas();
2030 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
2031 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
2032 gfx::Vector2d(-50, -50)));
2035 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
2036 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2037 host_impl_->SetViewportSize(gfx::Size(50, 50));
2038 DrawFrame();
2040 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
2041 DCHECK(scroll_layer);
2043 base::TimeTicks start_time =
2044 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
2045 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
2046 base::TimeTicks halfway_through_animation = start_time + duration / 2;
2047 base::TimeTicks end_time = start_time + duration;
2049 BeginFrameArgs begin_frame_args =
2050 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
2052 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
2053 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
2055 did_complete_page_scale_animation_ = false;
2056 host_impl_->active_tree()->SetPendingPageScaleAnimation(
2057 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
2058 gfx::Vector2d(), false, 2.f, duration)));
2059 host_impl_->ActivateSyncTree();
2060 begin_frame_args.frame_time = start_time;
2061 host_impl_->WillBeginImplFrame(begin_frame_args);
2062 host_impl_->Animate();
2063 EXPECT_FALSE(did_complete_page_scale_animation_);
2064 host_impl_->DidFinishImplFrame();
2066 begin_frame_args.frame_time = halfway_through_animation;
2067 host_impl_->WillBeginImplFrame(begin_frame_args);
2068 host_impl_->Animate();
2069 EXPECT_FALSE(did_complete_page_scale_animation_);
2070 host_impl_->DidFinishImplFrame();
2072 begin_frame_args.frame_time = end_time;
2073 host_impl_->WillBeginImplFrame(begin_frame_args);
2074 host_impl_->Animate();
2075 EXPECT_TRUE(did_complete_page_scale_animation_);
2076 host_impl_->DidFinishImplFrame();
2079 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
2080 public:
2081 LayerTreeHostImplOverridePhysicalTime(
2082 const LayerTreeSettings& settings,
2083 LayerTreeHostImplClient* client,
2084 Proxy* proxy,
2085 SharedBitmapManager* manager,
2086 TaskGraphRunner* task_graph_runner,
2087 RenderingStatsInstrumentation* rendering_stats_instrumentation)
2088 : LayerTreeHostImpl(settings,
2089 client,
2090 proxy,
2091 rendering_stats_instrumentation,
2092 manager,
2093 nullptr,
2094 task_graph_runner,
2095 0) {}
2097 BeginFrameArgs CurrentBeginFrameArgs() const override {
2098 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
2099 fake_current_physical_time_);
2102 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
2103 fake_current_physical_time_ = fake_now;
2106 private:
2107 base::TimeTicks fake_current_physical_time_;
2110 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
2111 protected:
2112 void SetupLayers(LayerTreeSettings settings) {
2113 gfx::Size content_size(100, 100);
2115 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
2116 new LayerTreeHostImplOverridePhysicalTime(
2117 settings, this, &proxy_, &shared_bitmap_manager_,
2118 &task_graph_runner_, &stats_instrumentation_);
2119 host_impl_ = make_scoped_ptr(host_impl_override_time);
2120 host_impl_->InitializeRenderer(CreateOutputSurface());
2122 SetupScrollAndContentsLayers(content_size);
2123 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
2124 host_impl_->SetViewportSize(
2125 gfx::Size(content_size.width() / 2, content_size.height() / 2));
2127 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
2128 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 400,
2129 VERTICAL, 10, 0, false, true);
2130 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
2132 LayerImpl* scroll = host_impl_->InnerViewportScrollLayer();
2133 LayerImpl* root = scroll->parent()->parent();
2134 scrollbar->SetScrollLayerAndClipLayerByIds(scroll->id(), root->id());
2135 root->AddChild(scrollbar.Pass());
2137 host_impl_->active_tree()->DidBecomeActive();
2138 DrawFrame();
2141 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
2142 LayerTreeSettings settings;
2143 settings.scrollbar_animator = animator;
2144 settings.scrollbar_fade_delay_ms = 20;
2145 settings.scrollbar_fade_duration_ms = 20;
2147 SetupLayers(settings);
2149 base::TimeTicks fake_now = base::TimeTicks::Now();
2151 EXPECT_FALSE(did_request_animate_);
2152 EXPECT_FALSE(did_request_redraw_);
2153 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2154 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2156 // If no scroll happened during a scroll gesture, it should have no effect.
2157 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2158 host_impl_->ScrollEnd();
2159 EXPECT_FALSE(did_request_animate_);
2160 EXPECT_FALSE(did_request_redraw_);
2161 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2162 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2164 // After a scroll, a scrollbar animation should be scheduled about 20ms from
2165 // now.
2166 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2167 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2168 EXPECT_FALSE(did_request_animate_);
2169 EXPECT_TRUE(did_request_redraw_);
2170 did_request_redraw_ = false;
2171 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2172 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2174 host_impl_->ScrollEnd();
2175 EXPECT_FALSE(did_request_animate_);
2176 EXPECT_FALSE(did_request_redraw_);
2177 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2178 requested_animation_delay_);
2179 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2181 fake_now += requested_animation_delay_;
2182 requested_animation_delay_ = base::TimeDelta();
2183 animation_task_.Run();
2184 animation_task_ = base::Closure();
2185 EXPECT_TRUE(did_request_animate_);
2186 did_request_animate_ = false;
2187 EXPECT_FALSE(did_request_redraw_);
2189 // After the scrollbar animation begins, we should start getting redraws.
2190 BeginFrameArgs begin_frame_args =
2191 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, fake_now);
2192 host_impl_->WillBeginImplFrame(begin_frame_args);
2193 host_impl_->Animate();
2194 EXPECT_TRUE(did_request_animate_);
2195 did_request_animate_ = false;
2196 EXPECT_TRUE(did_request_redraw_);
2197 did_request_redraw_ = false;
2198 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2199 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2200 host_impl_->DidFinishImplFrame();
2202 // Setting the scroll offset outside a scroll should also cause the
2203 // scrollbar to appear and to schedule a scrollbar animation.
2204 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2205 gfx::ScrollOffset(5, 5));
2206 EXPECT_FALSE(did_request_animate_);
2207 EXPECT_FALSE(did_request_redraw_);
2208 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2209 requested_animation_delay_);
2210 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2211 requested_animation_delay_ = base::TimeDelta();
2212 animation_task_ = base::Closure();
2214 // Scrollbar animation is not triggered unnecessarily.
2215 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2216 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2217 EXPECT_FALSE(did_request_animate_);
2218 EXPECT_TRUE(did_request_redraw_);
2219 did_request_redraw_ = false;
2220 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2221 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2223 host_impl_->ScrollEnd();
2224 EXPECT_FALSE(did_request_animate_);
2225 EXPECT_FALSE(did_request_redraw_);
2226 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2227 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2229 // Changing page scale triggers scrollbar animation.
2230 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
2231 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.1f);
2232 EXPECT_FALSE(did_request_animate_);
2233 EXPECT_FALSE(did_request_redraw_);
2234 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2235 requested_animation_delay_);
2236 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2237 requested_animation_delay_ = base::TimeDelta();
2238 animation_task_ = base::Closure();
2242 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
2243 RunTest(LayerTreeSettings::LINEAR_FADE);
2246 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
2247 RunTest(LayerTreeSettings::THINNING);
2250 class LayerTreeHostImplTestScrollbarOpacity : public LayerTreeHostImplTest {
2251 protected:
2252 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
2253 LayerTreeSettings settings;
2254 settings.scrollbar_animator = animator;
2255 settings.scrollbar_fade_delay_ms = 20;
2256 settings.scrollbar_fade_duration_ms = 20;
2257 settings.verify_property_trees = true;
2258 gfx::Size content_size(100, 100);
2260 CreateHostImpl(settings, CreateOutputSurface());
2261 host_impl_->CreatePendingTree();
2262 CreateScrollAndContentsLayers(host_impl_->pending_tree(), content_size);
2263 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
2264 SolidColorScrollbarLayerImpl::Create(host_impl_->pending_tree(), 400,
2265 VERTICAL, 10, 0, false, true);
2266 LayerImpl* scroll = host_impl_->pending_tree()->InnerViewportScrollLayer();
2267 LayerImpl* root = scroll->parent()->parent();
2268 scrollbar->SetScrollLayerAndClipLayerByIds(scroll->id(), root->id());
2269 root->AddChild(scrollbar.Pass());
2270 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
2271 host_impl_->pending_tree()->BuildPropertyTreesForTesting();
2272 host_impl_->ActivateSyncTree();
2274 LayerImpl* scrollbar_layer = host_impl_->active_tree()->LayerById(400);
2276 EffectNode* active_tree_node =
2277 host_impl_->active_tree()->property_trees()->effect_tree.Node(
2278 scrollbar_layer->effect_tree_index());
2279 EXPECT_FLOAT_EQ(scrollbar_layer->opacity(), active_tree_node->data.opacity);
2281 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2282 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2283 host_impl_->ScrollEnd();
2284 host_impl_->CreatePendingTree();
2285 EffectNode* pending_tree_node =
2286 host_impl_->pending_tree()->property_trees()->effect_tree.Node(
2287 scrollbar_layer->effect_tree_index());
2288 EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity);
2289 EXPECT_FLOAT_EQ(1.f, scrollbar_layer->opacity());
2290 EXPECT_FLOAT_EQ(0.f, pending_tree_node->data.opacity);
2291 host_impl_->ActivateSyncTree();
2292 active_tree_node =
2293 host_impl_->active_tree()->property_trees()->effect_tree.Node(
2294 scrollbar_layer->effect_tree_index());
2295 EXPECT_FLOAT_EQ(1.f, active_tree_node->data.opacity);
2296 EXPECT_FLOAT_EQ(1.f, scrollbar_layer->opacity());
2300 TEST_F(LayerTreeHostImplTestScrollbarOpacity, LinearFade) {
2301 RunTest(LayerTreeSettings::LINEAR_FADE);
2304 TEST_F(LayerTreeHostImplTestScrollbarOpacity, Thinning) {
2305 RunTest(LayerTreeSettings::THINNING);
2308 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2309 float device_scale_factor) {
2310 LayerTreeSettings settings;
2311 settings.scrollbar_fade_delay_ms = 500;
2312 settings.scrollbar_fade_duration_ms = 300;
2313 settings.scrollbar_animator = LayerTreeSettings::THINNING;
2315 gfx::Size viewport_size(300, 200);
2316 gfx::Size device_viewport_size = gfx::ToFlooredSize(
2317 gfx::ScaleSize(viewport_size, device_scale_factor));
2318 gfx::Size content_size(1000, 1000);
2320 CreateHostImpl(settings, CreateOutputSurface());
2321 host_impl_->SetDeviceScaleFactor(device_scale_factor);
2322 host_impl_->SetViewportSize(device_viewport_size);
2324 scoped_ptr<LayerImpl> root =
2325 LayerImpl::Create(host_impl_->active_tree(), 1);
2326 root->SetBounds(viewport_size);
2327 root->SetHasRenderSurface(true);
2329 scoped_ptr<LayerImpl> scroll =
2330 LayerImpl::Create(host_impl_->active_tree(), 2);
2331 scroll->SetScrollClipLayer(root->id());
2332 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2333 scroll->SetBounds(content_size);
2334 scroll->SetIsContainerForFixedPositionLayers(true);
2336 scoped_ptr<LayerImpl> contents =
2337 LayerImpl::Create(host_impl_->active_tree(), 3);
2338 contents->SetDrawsContent(true);
2339 contents->SetBounds(content_size);
2341 // The scrollbar is on the right side.
2342 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
2343 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
2344 scrollbar->SetDrawsContent(true);
2345 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
2346 scrollbar->SetPosition(gfx::Point(285, 0));
2348 scroll->AddChild(contents.Pass());
2349 root->AddChild(scroll.Pass());
2350 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
2351 root->AddChild(scrollbar.Pass());
2353 host_impl_->active_tree()->SetRootLayer(root.Pass());
2354 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
2355 Layer::INVALID_ID);
2356 host_impl_->active_tree()->DidBecomeActive();
2357 DrawFrame();
2359 LayerImpl* root_scroll =
2360 host_impl_->active_tree()->InnerViewportScrollLayer();
2361 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
2362 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
2363 static_cast<ScrollbarAnimationControllerThinning*>(
2364 root_scroll->scrollbar_animation_controller());
2365 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
2367 host_impl_->MouseMoveAt(gfx::Point(1, 1));
2368 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2370 host_impl_->MouseMoveAt(gfx::Point(200, 50));
2371 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2373 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2374 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2376 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
2377 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2378 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2380 did_request_redraw_ = false;
2381 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2382 host_impl_->MouseMoveAt(gfx::Point(290, 100));
2383 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2384 host_impl_->MouseMoveAt(gfx::Point(290, 120));
2385 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2386 host_impl_->MouseMoveAt(gfx::Point(150, 120));
2387 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2390 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
2391 SetupMouseMoveAtWithDeviceScale(1.f);
2394 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
2395 SetupMouseMoveAtWithDeviceScale(2.f);
2398 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
2399 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2400 host_impl_->SetViewportSize(gfx::Size(50, 50));
2401 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
2402 DrawFrame();
2404 CompositorFrameMetadata metadata =
2405 host_impl_->MakeCompositorFrameMetadata();
2406 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
2407 EXPECT_EQ(1.f, metadata.page_scale_factor);
2408 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
2409 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2410 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2411 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2412 EXPECT_FALSE(metadata.root_overflow_x_hidden);
2413 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2416 // Scrolling should update metadata immediately.
2417 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2418 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2419 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2421 CompositorFrameMetadata metadata =
2422 host_impl_->MakeCompositorFrameMetadata();
2423 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2425 host_impl_->ScrollEnd();
2427 CompositorFrameMetadata metadata =
2428 host_impl_->MakeCompositorFrameMetadata();
2429 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2432 // Root "overflow: hidden" properties should be reflected on the outer
2433 // viewport scroll layer.
2435 host_impl_->active_tree()
2436 ->OuterViewportScrollLayer()
2437 ->set_user_scrollable_horizontal(false);
2438 CompositorFrameMetadata metadata =
2439 host_impl_->MakeCompositorFrameMetadata();
2440 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2441 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2443 host_impl_->active_tree()
2444 ->OuterViewportScrollLayer()
2445 ->set_user_scrollable_vertical(false);
2446 metadata = host_impl_->MakeCompositorFrameMetadata();
2447 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2448 EXPECT_TRUE(metadata.root_overflow_y_hidden);
2451 // Re-enable scrollability and verify that overflows are no longer hidden.
2453 host_impl_->active_tree()
2454 ->OuterViewportScrollLayer()
2455 ->set_user_scrollable_horizontal(true);
2456 host_impl_->active_tree()
2457 ->OuterViewportScrollLayer()
2458 ->set_user_scrollable_vertical(true);
2459 CompositorFrameMetadata metadata =
2460 host_impl_->MakeCompositorFrameMetadata();
2461 EXPECT_FALSE(metadata.root_overflow_x_hidden);
2462 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2465 // Root "overflow: hidden" properties should also be reflected on the
2466 // inner viewport scroll layer.
2468 host_impl_->active_tree()
2469 ->InnerViewportScrollLayer()
2470 ->set_user_scrollable_horizontal(false);
2471 CompositorFrameMetadata metadata =
2472 host_impl_->MakeCompositorFrameMetadata();
2473 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2474 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2476 host_impl_->active_tree()
2477 ->InnerViewportScrollLayer()
2478 ->set_user_scrollable_vertical(false);
2479 metadata = host_impl_->MakeCompositorFrameMetadata();
2480 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2481 EXPECT_TRUE(metadata.root_overflow_y_hidden);
2484 // Page scale should update metadata correctly (shrinking only the viewport).
2485 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
2486 host_impl_->PinchGestureBegin();
2487 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
2488 host_impl_->PinchGestureEnd();
2489 host_impl_->ScrollEnd();
2491 CompositorFrameMetadata metadata =
2492 host_impl_->MakeCompositorFrameMetadata();
2493 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2494 EXPECT_EQ(2.f, metadata.page_scale_factor);
2495 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
2496 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2497 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2498 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2501 // Likewise if set from the main thread.
2502 host_impl_->ProcessScrollDeltas();
2503 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
2504 host_impl_->active_tree()->SetPageScaleOnActiveTree(4.f);
2506 CompositorFrameMetadata metadata =
2507 host_impl_->MakeCompositorFrameMetadata();
2508 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2509 EXPECT_EQ(4.f, metadata.page_scale_factor);
2510 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
2511 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2512 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2513 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2517 class DidDrawCheckLayer : public LayerImpl {
2518 public:
2519 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
2520 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
2523 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
2524 will_draw_called_ = true;
2525 if (will_draw_returns_false_)
2526 return false;
2527 return LayerImpl::WillDraw(draw_mode, provider);
2530 void AppendQuads(RenderPass* render_pass,
2531 AppendQuadsData* append_quads_data) override {
2532 append_quads_called_ = true;
2533 LayerImpl::AppendQuads(render_pass, append_quads_data);
2536 void DidDraw(ResourceProvider* provider) override {
2537 did_draw_called_ = true;
2538 LayerImpl::DidDraw(provider);
2541 bool will_draw_called() const { return will_draw_called_; }
2542 bool append_quads_called() const { return append_quads_called_; }
2543 bool did_draw_called() const { return did_draw_called_; }
2545 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
2547 void ClearDidDrawCheck() {
2548 will_draw_called_ = false;
2549 append_quads_called_ = false;
2550 did_draw_called_ = false;
2553 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
2555 void AddCopyRequest() {
2556 ScopedPtrVector<CopyOutputRequest> requests;
2557 requests.push_back(
2558 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
2559 SetHasRenderSurface(true);
2560 PassCopyRequests(&requests);
2563 protected:
2564 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
2565 : LayerImpl(tree_impl, id),
2566 will_draw_returns_false_(false),
2567 will_draw_called_(false),
2568 append_quads_called_(false),
2569 did_draw_called_(false) {
2570 SetBounds(gfx::Size(10, 10));
2571 SetDrawsContent(true);
2572 draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10);
2575 private:
2576 bool will_draw_returns_false_;
2577 bool will_draw_called_;
2578 bool append_quads_called_;
2579 bool did_draw_called_;
2582 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
2583 // The root layer is always drawn, so run this test on a child layer that
2584 // will be masked out by the root layer's bounds.
2585 host_impl_->active_tree()->SetRootLayer(
2586 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2587 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2588 host_impl_->active_tree()->root_layer());
2590 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2591 root->SetHasRenderSurface(true);
2592 DidDrawCheckLayer* layer =
2593 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2596 LayerTreeHostImpl::FrameData frame;
2597 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2598 host_impl_->DrawLayers(&frame);
2599 host_impl_->DidDrawAllLayers(frame);
2601 EXPECT_TRUE(layer->will_draw_called());
2602 EXPECT_TRUE(layer->append_quads_called());
2603 EXPECT_TRUE(layer->did_draw_called());
2606 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
2609 LayerTreeHostImpl::FrameData frame;
2611 layer->set_will_draw_returns_false();
2612 layer->ClearDidDrawCheck();
2614 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2615 host_impl_->DrawLayers(&frame);
2616 host_impl_->DidDrawAllLayers(frame);
2618 EXPECT_TRUE(layer->will_draw_called());
2619 EXPECT_FALSE(layer->append_quads_called());
2620 EXPECT_FALSE(layer->did_draw_called());
2624 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
2625 // The root layer is always drawn, so run this test on a child layer that
2626 // will be masked out by the root layer's bounds.
2627 host_impl_->active_tree()->SetRootLayer(
2628 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2629 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2630 host_impl_->active_tree()->root_layer());
2631 root->SetMasksToBounds(true);
2632 root->SetHasRenderSurface(true);
2633 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2634 DidDrawCheckLayer* layer =
2635 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2636 // Ensure visible_layer_rect for layer is empty.
2637 layer->SetPosition(gfx::PointF(100.f, 100.f));
2638 layer->SetBounds(gfx::Size(10, 10));
2640 LayerTreeHostImpl::FrameData frame;
2642 EXPECT_FALSE(layer->will_draw_called());
2643 EXPECT_FALSE(layer->did_draw_called());
2645 host_impl_->active_tree()->BuildPropertyTreesForTesting();
2646 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2647 host_impl_->DrawLayers(&frame);
2648 host_impl_->DidDrawAllLayers(frame);
2650 EXPECT_FALSE(layer->will_draw_called());
2651 EXPECT_FALSE(layer->did_draw_called());
2653 EXPECT_TRUE(layer->visible_layer_rect().IsEmpty());
2655 // Ensure visible_layer_rect for layer is not empty
2656 layer->SetPosition(gfx::PointF());
2658 EXPECT_FALSE(layer->will_draw_called());
2659 EXPECT_FALSE(layer->did_draw_called());
2661 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2662 host_impl_->DrawLayers(&frame);
2663 host_impl_->DidDrawAllLayers(frame);
2665 EXPECT_TRUE(layer->will_draw_called());
2666 EXPECT_TRUE(layer->did_draw_called());
2668 EXPECT_FALSE(layer->visible_layer_rect().IsEmpty());
2671 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
2672 gfx::Size big_size(1000, 1000);
2673 host_impl_->SetViewportSize(big_size);
2675 host_impl_->active_tree()->SetRootLayer(
2676 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2677 DidDrawCheckLayer* root =
2678 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2680 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2681 DidDrawCheckLayer* occluded_layer =
2682 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2684 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2685 root->SetHasRenderSurface(true);
2686 DidDrawCheckLayer* top_layer =
2687 static_cast<DidDrawCheckLayer*>(root->children()[1]);
2688 // This layer covers the occluded_layer above. Make this layer large so it can
2689 // occlude.
2690 top_layer->SetBounds(big_size);
2691 top_layer->SetContentsOpaque(true);
2693 LayerTreeHostImpl::FrameData frame;
2695 EXPECT_FALSE(occluded_layer->will_draw_called());
2696 EXPECT_FALSE(occluded_layer->did_draw_called());
2697 EXPECT_FALSE(top_layer->will_draw_called());
2698 EXPECT_FALSE(top_layer->did_draw_called());
2700 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2701 host_impl_->DrawLayers(&frame);
2702 host_impl_->DidDrawAllLayers(frame);
2704 EXPECT_FALSE(occluded_layer->will_draw_called());
2705 EXPECT_FALSE(occluded_layer->did_draw_called());
2706 EXPECT_TRUE(top_layer->will_draw_called());
2707 EXPECT_TRUE(top_layer->did_draw_called());
2710 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
2711 host_impl_->active_tree()->SetRootLayer(
2712 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2713 DidDrawCheckLayer* root =
2714 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2716 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2717 root->SetHasRenderSurface(true);
2718 DidDrawCheckLayer* layer1 =
2719 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2721 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2722 DidDrawCheckLayer* layer2 =
2723 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
2725 layer1->SetHasRenderSurface(true);
2726 layer1->SetShouldFlattenTransform(true);
2728 EXPECT_FALSE(root->did_draw_called());
2729 EXPECT_FALSE(layer1->did_draw_called());
2730 EXPECT_FALSE(layer2->did_draw_called());
2732 LayerTreeHostImpl::FrameData frame;
2733 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2734 host_impl_->active_tree()->root_layer());
2735 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2736 host_impl_->DrawLayers(&frame);
2737 host_impl_->DidDrawAllLayers(frame);
2739 EXPECT_TRUE(root->did_draw_called());
2740 EXPECT_TRUE(layer1->did_draw_called());
2741 EXPECT_TRUE(layer2->did_draw_called());
2743 EXPECT_NE(root->render_surface(), layer1->render_surface());
2744 EXPECT_TRUE(layer1->render_surface());
2747 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
2748 public:
2749 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2750 int id,
2751 bool tile_missing,
2752 bool had_incomplete_tile,
2753 bool animating,
2754 ResourceProvider* resource_provider) {
2755 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
2757 tile_missing,
2758 had_incomplete_tile,
2759 animating,
2760 resource_provider));
2763 void AppendQuads(RenderPass* render_pass,
2764 AppendQuadsData* append_quads_data) override {
2765 LayerImpl::AppendQuads(render_pass, append_quads_data);
2766 if (had_incomplete_tile_)
2767 append_quads_data->num_incomplete_tiles++;
2768 if (tile_missing_)
2769 append_quads_data->num_missing_tiles++;
2772 private:
2773 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
2774 int id,
2775 bool tile_missing,
2776 bool had_incomplete_tile,
2777 bool animating,
2778 ResourceProvider* resource_provider)
2779 : DidDrawCheckLayer(tree_impl, id),
2780 tile_missing_(tile_missing),
2781 had_incomplete_tile_(had_incomplete_tile) {
2782 if (animating)
2783 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2786 bool tile_missing_;
2787 bool had_incomplete_tile_;
2790 struct PrepareToDrawSuccessTestCase {
2791 struct State {
2792 bool has_missing_tile = false;
2793 bool has_incomplete_tile = false;
2794 bool is_animating = false;
2795 bool has_copy_request = false;
2797 bool high_res_required = false;
2798 State layer_before;
2799 State layer_between;
2800 State layer_after;
2801 DrawResult expected_result;
2803 explicit PrepareToDrawSuccessTestCase(DrawResult result)
2804 : expected_result(result) {}
2807 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
2808 std::vector<PrepareToDrawSuccessTestCase> cases;
2810 // 0. Default case.
2811 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2812 // 1. Animated layer first.
2813 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2814 cases.back().layer_before.is_animating = true;
2815 // 2. Animated layer between.
2816 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2817 cases.back().layer_between.is_animating = true;
2818 // 3. Animated layer last.
2819 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2820 cases.back().layer_after.is_animating = true;
2821 // 4. Missing tile first.
2822 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2823 cases.back().layer_before.has_missing_tile = true;
2824 // 5. Missing tile between.
2825 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2826 cases.back().layer_between.has_missing_tile = true;
2827 // 6. Missing tile last.
2828 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2829 cases.back().layer_after.has_missing_tile = true;
2830 // 7. Incomplete tile first.
2831 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2832 cases.back().layer_before.has_incomplete_tile = true;
2833 // 8. Incomplete tile between.
2834 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2835 cases.back().layer_between.has_incomplete_tile = true;
2836 // 9. Incomplete tile last.
2837 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2838 cases.back().layer_after.has_incomplete_tile = true;
2839 // 10. Animation with missing tile.
2840 cases.push_back(
2841 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
2842 cases.back().layer_between.has_missing_tile = true;
2843 cases.back().layer_between.is_animating = true;
2844 // 11. Animation with incomplete tile.
2845 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2846 cases.back().layer_between.has_incomplete_tile = true;
2847 cases.back().layer_between.is_animating = true;
2849 // 12. High res required.
2850 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2851 cases.back().high_res_required = true;
2852 // 13. High res required with incomplete tile.
2853 cases.push_back(
2854 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2855 cases.back().high_res_required = true;
2856 cases.back().layer_between.has_incomplete_tile = true;
2857 // 14. High res required with missing tile.
2858 cases.push_back(
2859 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2860 cases.back().high_res_required = true;
2861 cases.back().layer_between.has_missing_tile = true;
2863 // 15. High res required is higher priority than animating missing tiles.
2864 cases.push_back(
2865 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2866 cases.back().high_res_required = true;
2867 cases.back().layer_between.has_missing_tile = true;
2868 cases.back().layer_after.has_missing_tile = true;
2869 cases.back().layer_after.is_animating = true;
2870 // 16. High res required is higher priority than animating missing tiles.
2871 cases.push_back(
2872 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2873 cases.back().high_res_required = true;
2874 cases.back().layer_between.has_missing_tile = true;
2875 cases.back().layer_before.has_missing_tile = true;
2876 cases.back().layer_before.is_animating = true;
2878 host_impl_->active_tree()->SetRootLayer(
2879 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2880 DidDrawCheckLayer* root =
2881 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2882 root->SetHasRenderSurface(true);
2884 LayerTreeHostImpl::FrameData frame;
2885 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2886 host_impl_->DrawLayers(&frame);
2887 host_impl_->DidDrawAllLayers(frame);
2888 host_impl_->SwapBuffers(frame);
2890 for (size_t i = 0; i < cases.size(); ++i) {
2891 const auto& testcase = cases[i];
2892 std::vector<LayerImpl*> to_remove;
2893 for (auto* child : root->children())
2894 to_remove.push_back(child);
2895 for (auto* child : to_remove)
2896 root->RemoveChild(child);
2898 std::ostringstream scope;
2899 scope << "Test case: " << i;
2900 SCOPED_TRACE(scope.str());
2902 root->AddChild(MissingTextureAnimatingLayer::Create(
2903 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2904 testcase.layer_before.has_incomplete_tile,
2905 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2906 DidDrawCheckLayer* before =
2907 static_cast<DidDrawCheckLayer*>(root->children().back());
2908 if (testcase.layer_before.has_copy_request)
2909 before->AddCopyRequest();
2911 root->AddChild(MissingTextureAnimatingLayer::Create(
2912 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2913 testcase.layer_between.has_incomplete_tile,
2914 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2915 DidDrawCheckLayer* between =
2916 static_cast<DidDrawCheckLayer*>(root->children().back());
2917 if (testcase.layer_between.has_copy_request)
2918 between->AddCopyRequest();
2920 root->AddChild(MissingTextureAnimatingLayer::Create(
2921 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2922 testcase.layer_after.has_incomplete_tile,
2923 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2924 DidDrawCheckLayer* after =
2925 static_cast<DidDrawCheckLayer*>(root->children().back());
2926 if (testcase.layer_after.has_copy_request)
2927 after->AddCopyRequest();
2929 if (testcase.high_res_required)
2930 host_impl_->SetRequiresHighResToDraw();
2932 LayerTreeHostImpl::FrameData frame;
2933 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2934 host_impl_->DrawLayers(&frame);
2935 host_impl_->DidDrawAllLayers(frame);
2936 host_impl_->SwapBuffers(frame);
2940 TEST_F(LayerTreeHostImplTest,
2941 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
2942 CreateHostImpl(DefaultSettings(),
2943 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2944 EXPECT_TRUE(host_impl_->output_surface()
2945 ->capabilities()
2946 .draw_and_swap_full_viewport_every_frame);
2948 std::vector<PrepareToDrawSuccessTestCase> cases;
2950 // 0. Default case.
2951 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2952 // 1. Animation with missing tile.
2953 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2954 cases.back().layer_between.has_missing_tile = true;
2955 cases.back().layer_between.is_animating = true;
2956 // 2. High res required with incomplete tile.
2957 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2958 cases.back().high_res_required = true;
2959 cases.back().layer_between.has_incomplete_tile = true;
2960 // 3. High res required with missing tile.
2961 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2962 cases.back().high_res_required = true;
2963 cases.back().layer_between.has_missing_tile = true;
2965 host_impl_->active_tree()->SetRootLayer(
2966 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2967 DidDrawCheckLayer* root =
2968 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2969 root->SetHasRenderSurface(true);
2971 LayerTreeHostImpl::FrameData frame;
2972 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2973 host_impl_->DrawLayers(&frame);
2974 host_impl_->DidDrawAllLayers(frame);
2975 host_impl_->SwapBuffers(frame);
2977 for (size_t i = 0; i < cases.size(); ++i) {
2978 const auto& testcase = cases[i];
2979 std::vector<LayerImpl*> to_remove;
2980 for (auto* child : root->children())
2981 to_remove.push_back(child);
2982 for (auto* child : to_remove)
2983 root->RemoveChild(child);
2985 std::ostringstream scope;
2986 scope << "Test case: " << i;
2987 SCOPED_TRACE(scope.str());
2989 root->AddChild(MissingTextureAnimatingLayer::Create(
2990 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2991 testcase.layer_before.has_incomplete_tile,
2992 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2993 DidDrawCheckLayer* before =
2994 static_cast<DidDrawCheckLayer*>(root->children().back());
2995 if (testcase.layer_before.has_copy_request)
2996 before->AddCopyRequest();
2998 root->AddChild(MissingTextureAnimatingLayer::Create(
2999 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
3000 testcase.layer_between.has_incomplete_tile,
3001 testcase.layer_between.is_animating, host_impl_->resource_provider()));
3002 DidDrawCheckLayer* between =
3003 static_cast<DidDrawCheckLayer*>(root->children().back());
3004 if (testcase.layer_between.has_copy_request)
3005 between->AddCopyRequest();
3007 root->AddChild(MissingTextureAnimatingLayer::Create(
3008 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
3009 testcase.layer_after.has_incomplete_tile,
3010 testcase.layer_after.is_animating, host_impl_->resource_provider()));
3011 DidDrawCheckLayer* after =
3012 static_cast<DidDrawCheckLayer*>(root->children().back());
3013 if (testcase.layer_after.has_copy_request)
3014 after->AddCopyRequest();
3016 if (testcase.high_res_required)
3017 host_impl_->SetRequiresHighResToDraw();
3019 LayerTreeHostImpl::FrameData frame;
3020 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
3021 host_impl_->DrawLayers(&frame);
3022 host_impl_->DidDrawAllLayers(frame);
3023 host_impl_->SwapBuffers(frame);
3027 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
3028 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3029 root->SetScrollClipLayer(Layer::INVALID_ID);
3030 root->SetHasRenderSurface(true);
3031 host_impl_->active_tree()->SetRootLayer(root.Pass());
3032 DrawFrame();
3034 // Scroll event is ignored because layer is not scrollable.
3035 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3036 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3037 EXPECT_FALSE(did_request_redraw_);
3038 EXPECT_FALSE(did_request_commit_);
3041 TEST_F(LayerTreeHostImplTest, ClampingAfterActivation) {
3042 host_impl_->CreatePendingTree();
3043 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
3044 CreateScrollAndContentsLayers(host_impl_->pending_tree(),
3045 gfx::Size(100, 100));
3046 host_impl_->ActivateSyncTree();
3048 host_impl_->CreatePendingTree();
3049 const gfx::ScrollOffset pending_scroll = gfx::ScrollOffset(-100, -100);
3050 LayerImpl* active_outer_layer =
3051 host_impl_->active_tree()->OuterViewportScrollLayer();
3052 LayerImpl* pending_outer_layer =
3053 host_impl_->pending_tree()->OuterViewportScrollLayer();
3054 pending_outer_layer->PushScrollOffsetFromMainThread(pending_scroll);
3056 host_impl_->ActivateSyncTree();
3057 // Scrolloffsets on the active tree will be clamped after activation.
3058 EXPECT_EQ(active_outer_layer->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
3061 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
3062 public:
3063 LayerTreeHostImplTopControlsTest()
3064 // Make the clip size the same as the layer (content) size so the layer is
3065 // non-scrollable.
3066 : layer_size_(10, 10),
3067 clip_size_(layer_size_),
3068 top_controls_height_(50) {
3069 viewport_size_ = gfx::Size(clip_size_.width(),
3070 clip_size_.height() + top_controls_height_);
3073 bool CreateHostImpl(const LayerTreeSettings& settings,
3074 scoped_ptr<OutputSurface> output_surface) override {
3075 bool init =
3076 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
3077 if (init) {
3078 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
3079 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
3080 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
3082 return init;
3085 void SetupTopControlsAndScrollLayerWithVirtualViewport(
3086 const gfx::Size& inner_viewport_size,
3087 const gfx::Size& outer_viewport_size,
3088 const gfx::Size& scroll_layer_size) {
3089 CreateHostImpl(settings_, CreateOutputSurface());
3090 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
3091 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
3092 host_impl_->DidChangeTopControlsPosition();
3094 scoped_ptr<LayerImpl> root =
3095 LayerImpl::Create(host_impl_->active_tree(), 1);
3096 scoped_ptr<LayerImpl> root_clip =
3097 LayerImpl::Create(host_impl_->active_tree(), 2);
3098 scoped_ptr<LayerImpl> page_scale =
3099 LayerImpl::Create(host_impl_->active_tree(), 3);
3101 scoped_ptr<LayerImpl> outer_scroll =
3102 LayerImpl::Create(host_impl_->active_tree(), 4);
3103 scoped_ptr<LayerImpl> outer_clip =
3104 LayerImpl::Create(host_impl_->active_tree(), 5);
3106 root_clip->SetBounds(inner_viewport_size);
3107 root->SetScrollClipLayer(root_clip->id());
3108 root->SetBounds(outer_viewport_size);
3109 root->SetPosition(gfx::PointF());
3110 root->SetDrawsContent(false);
3111 root->SetIsContainerForFixedPositionLayers(true);
3112 root_clip->SetHasRenderSurface(true);
3113 outer_clip->SetBounds(outer_viewport_size);
3114 outer_scroll->SetScrollClipLayer(outer_clip->id());
3115 outer_scroll->SetBounds(scroll_layer_size);
3116 outer_scroll->SetPosition(gfx::PointF());
3117 outer_scroll->SetDrawsContent(false);
3118 outer_scroll->SetIsContainerForFixedPositionLayers(true);
3120 int inner_viewport_scroll_layer_id = root->id();
3121 int outer_viewport_scroll_layer_id = outer_scroll->id();
3122 int page_scale_layer_id = page_scale->id();
3124 outer_clip->AddChild(outer_scroll.Pass());
3125 root->AddChild(outer_clip.Pass());
3126 page_scale->AddChild(root.Pass());
3127 root_clip->AddChild(page_scale.Pass());
3129 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3130 host_impl_->active_tree()->SetViewportLayersFromIds(
3131 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
3132 outer_viewport_scroll_layer_id);
3134 host_impl_->SetViewportSize(inner_viewport_size);
3135 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3136 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
3139 protected:
3140 gfx::Size layer_size_;
3141 gfx::Size clip_size_;
3142 gfx::Size viewport_size_;
3143 float top_controls_height_;
3145 LayerTreeSettings settings_;
3146 }; // class LayerTreeHostImplTopControlsTest
3148 // Tests that, on a page with content the same size as the viewport, hiding
3149 // the top controls also increases the ScrollableSize (i.e. the content size).
3150 // Since the viewport got larger, the effective scrollable "content" also did.
3151 // This ensures, for one thing, that the overscroll glow is shown in the right
3152 // place.
3153 TEST_F(LayerTreeHostImplTopControlsTest,
3154 HidingTopControlsExpandsScrollableSize) {
3155 SetupTopControlsAndScrollLayerWithVirtualViewport(
3156 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
3158 LayerTreeImpl* active_tree = host_impl_->active_tree();
3160 // Create a content layer beneath the outer viewport scroll layer.
3161 int id = host_impl_->OuterViewportScrollLayer()->id();
3162 host_impl_->OuterViewportScrollLayer()->AddChild(
3163 LayerImpl::Create(host_impl_->active_tree(), id + 2));
3164 LayerImpl* content = active_tree->OuterViewportScrollLayer()->children()[0];
3165 content->SetBounds(gfx::Size(50, 50));
3167 DrawFrame();
3169 LayerImpl* inner_container = active_tree->InnerViewportContainerLayer();
3170 LayerImpl* outer_container = active_tree->OuterViewportContainerLayer();
3172 // The top controls should start off showing so the viewport should be shrunk.
3173 ASSERT_EQ(gfx::Size(50, 50), inner_container->bounds());
3174 ASSERT_EQ(gfx::Size(50, 50), outer_container->bounds());
3176 EXPECT_EQ(gfx::SizeF(50, 50), active_tree->ScrollableSize());
3178 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3179 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3181 host_impl_->top_controls_manager()->ScrollBegin();
3183 // Hide the top controls by a bit, the scrollable size should increase but the
3184 // actual content bounds shouldn't.
3186 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
3187 ASSERT_EQ(gfx::Size(50, 75), inner_container->bounds());
3188 ASSERT_EQ(gfx::Size(50, 75), outer_container->bounds());
3189 EXPECT_EQ(gfx::SizeF(50, 75), active_tree->ScrollableSize());
3190 EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
3193 // Fully hide the top controls.
3195 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
3196 ASSERT_EQ(gfx::Size(50, 100), inner_container->bounds());
3197 ASSERT_EQ(gfx::Size(50, 100), outer_container->bounds());
3198 EXPECT_EQ(gfx::SizeF(50, 100), active_tree->ScrollableSize());
3199 EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
3202 // Scrolling additionally shouldn't have any effect.
3204 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 25.f));
3205 ASSERT_EQ(gfx::Size(50, 100), inner_container->bounds());
3206 ASSERT_EQ(gfx::Size(50, 100), outer_container->bounds());
3207 EXPECT_EQ(gfx::SizeF(50, 100), active_tree->ScrollableSize());
3208 EXPECT_EQ(gfx::SizeF(50, 50), content->BoundsForScrolling());
3211 host_impl_->top_controls_manager()->ScrollEnd();
3212 host_impl_->ScrollEnd();
3215 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
3216 SetupTopControlsAndScrollLayerWithVirtualViewport(
3217 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
3218 DrawFrame();
3220 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3221 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3223 // Make the test scroll delta a fractional amount, to verify that the
3224 // fixed container size delta is (1) non-zero, and (2) fractional, and
3225 // (3) matches the movement of the top controls.
3226 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
3227 host_impl_->top_controls_manager()->ScrollBegin();
3228 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3229 host_impl_->top_controls_manager()->ScrollEnd();
3231 LayerImpl* inner_viewport_scroll_layer =
3232 host_impl_->active_tree()->InnerViewportScrollLayer();
3233 DCHECK(inner_viewport_scroll_layer);
3234 host_impl_->ScrollEnd();
3235 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
3236 inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
3239 // In this test, the outer viewport is initially unscrollable. We test that a
3240 // scroll initiated on the inner viewport, causing the top controls to show and
3241 // thus making the outer viewport scrollable, still scrolls the outer viewport.
3242 TEST_F(LayerTreeHostImplTopControlsTest,
3243 TopControlsOuterViewportBecomesScrollable) {
3244 SetupTopControlsAndScrollLayerWithVirtualViewport(
3245 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
3246 DrawFrame();
3248 LayerImpl* inner_scroll =
3249 host_impl_->active_tree()->InnerViewportScrollLayer();
3250 LayerImpl* inner_container =
3251 host_impl_->active_tree()->InnerViewportContainerLayer();
3252 LayerImpl* outer_scroll =
3253 host_impl_->active_tree()->OuterViewportScrollLayer();
3254 LayerImpl* outer_container =
3255 host_impl_->active_tree()->OuterViewportContainerLayer();
3257 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
3258 outer_scroll->SetDrawsContent(true);
3259 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
3261 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3262 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3263 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
3265 // The entire scroll delta should have been used to hide the top controls.
3266 // The viewport layers should be resized back to their full sizes.
3267 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3268 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
3269 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
3270 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
3272 // The inner viewport should be scrollable by 50px * page_scale.
3273 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
3274 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
3275 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
3276 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
3278 host_impl_->ScrollEnd();
3280 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3281 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3282 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
3284 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
3286 // The entire scroll delta should have been used to show the top controls.
3287 // The outer viewport should be resized to accomodate and scrolled to the
3288 // bottom of the document to keep the viewport in place.
3289 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3290 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
3291 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
3292 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
3293 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
3295 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3296 // since it wasn't scrollable when the scroll began.
3297 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
3298 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
3299 EXPECT_EQ(15.f, inner_scroll->CurrentScrollOffset().y());
3301 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
3302 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
3303 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
3305 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
3306 host_impl_->ScrollEnd();
3308 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
3309 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
3312 // Test that the fixed position container delta is appropriately adjusted
3313 // by the top controls showing/hiding and page scale doesn't affect it.
3314 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
3315 SetupTopControlsAndScrollLayerWithVirtualViewport(
3316 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3317 DrawFrame();
3318 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3320 float page_scale = 1.5f;
3321 LayerImpl* outer_viewport_scroll_layer =
3322 host_impl_->active_tree()->OuterViewportScrollLayer();
3324 // Zoom in, since the fixed container is the outer viewport, the delta should
3325 // not be scaled.
3326 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
3328 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3329 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3331 // Scroll down, the top controls hiding should expand the viewport size so
3332 // the delta should be equal to the scroll distance.
3333 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
3334 host_impl_->top_controls_manager()->ScrollBegin();
3335 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3336 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
3337 host_impl_->top_controls_manager()->ContentTopOffset());
3338 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
3339 outer_viewport_scroll_layer->FixedContainerSizeDelta().y());
3340 host_impl_->ScrollEnd();
3342 // Scroll past the maximum extent. The delta shouldn't be greater than the
3343 // top controls height.
3344 host_impl_->top_controls_manager()->ScrollBegin();
3345 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3346 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3347 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
3348 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3349 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
3350 outer_viewport_scroll_layer->FixedContainerSizeDelta());
3351 host_impl_->ScrollEnd();
3353 // Scroll in the direction to make the top controls show.
3354 host_impl_->top_controls_manager()->ScrollBegin();
3355 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
3356 EXPECT_EQ(top_controls_scroll_delta.y(),
3357 host_impl_->top_controls_manager()->ContentTopOffset());
3358 EXPECT_VECTOR_EQ(
3359 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
3360 outer_viewport_scroll_layer->FixedContainerSizeDelta());
3361 host_impl_->top_controls_manager()->ScrollEnd();
3364 // Test that if only the top controls are scrolled, we shouldn't request a
3365 // commit.
3366 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsDontTriggerCommit) {
3367 SetupTopControlsAndScrollLayerWithVirtualViewport(
3368 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3369 DrawFrame();
3371 // Show top controls
3372 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3374 // Scroll 25px to hide top controls
3375 gfx::Vector2dF scroll_delta(0.f, 25.f);
3376 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3377 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3378 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3379 EXPECT_FALSE(did_request_commit_);
3382 // Test that if a scrollable sublayer doesn't consume the scroll,
3383 // top controls should hide when scrolling down.
3384 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
3385 gfx::Size sub_content_size(100, 400);
3386 gfx::Size sub_content_layer_size(100, 300);
3387 SetupTopControlsAndScrollLayerWithVirtualViewport(
3388 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3389 DrawFrame();
3391 // Show top controls
3392 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3394 LayerImpl* outer_viewport_scroll_layer =
3395 host_impl_->active_tree()->OuterViewportScrollLayer();
3396 int id = outer_viewport_scroll_layer->id();
3398 scoped_ptr<LayerImpl> child =
3399 LayerImpl::Create(host_impl_->active_tree(), id + 2);
3400 scoped_ptr<LayerImpl> child_clip =
3401 LayerImpl::Create(host_impl_->active_tree(), id + 3);
3403 child_clip->SetBounds(sub_content_layer_size);
3404 child->SetScrollClipLayer(child_clip->id());
3405 child->SetBounds(sub_content_size);
3406 child->SetPosition(gfx::PointF());
3407 child->SetDrawsContent(true);
3408 child->SetIsContainerForFixedPositionLayers(true);
3410 // scroll child to limit
3411 child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
3412 child_clip->AddChild(child.Pass());
3413 outer_viewport_scroll_layer->AddChild(child_clip.Pass());
3415 // Scroll 25px to hide top controls
3416 gfx::Vector2dF scroll_delta(0.f, 25.f);
3417 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3418 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3419 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3420 host_impl_->ScrollEnd();
3422 // Top controls should be hidden
3423 EXPECT_EQ(scroll_delta.y(),
3424 top_controls_height_ -
3425 host_impl_->top_controls_manager()->ContentTopOffset());
3428 // Ensure setting the top controls position explicitly using the setters on the
3429 // TreeImpl correctly affects the top controls manager and viewport bounds.
3430 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
3431 CreateHostImpl(settings_, CreateOutputSurface());
3432 SetupTopControlsAndScrollLayerWithVirtualViewport(
3433 layer_size_, layer_size_, layer_size_);
3434 DrawFrame();
3436 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3437 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3438 30.f / top_controls_height_);
3439 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3440 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
3441 EXPECT_FLOAT_EQ(-20.f,
3442 host_impl_->top_controls_manager()->ControlsTopOffset());
3444 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3445 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3446 EXPECT_FLOAT_EQ(-50.f,
3447 host_impl_->top_controls_manager()->ControlsTopOffset());
3449 host_impl_->DidChangeTopControlsPosition();
3451 // Now that top controls have moved, expect the clip to resize.
3452 LayerImpl* inner_clip_ptr =
3453 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3454 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3457 // Test that the top_controls delta and sent delta are appropriately
3458 // applied on sync tree activation. The total top controls offset shouldn't
3459 // change after the activation.
3460 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
3461 CreateHostImpl(settings_, CreateOutputSurface());
3462 SetupTopControlsAndScrollLayerWithVirtualViewport(
3463 layer_size_, layer_size_, layer_size_);
3464 DrawFrame();
3466 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3467 20.f / top_controls_height_);
3468 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3469 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
3470 15.f / top_controls_height_);
3471 host_impl_->active_tree()
3472 ->top_controls_shown_ratio()
3473 ->PullDeltaForMainThread();
3474 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3475 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
3476 top_controls_height_);
3478 host_impl_->DidChangeTopControlsPosition();
3479 LayerImpl* inner_clip_ptr =
3480 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3481 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3482 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3484 host_impl_->ActivateSyncTree();
3486 inner_clip_ptr = host_impl_->InnerViewportScrollLayer()->parent()->parent();
3487 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3488 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3490 EXPECT_FLOAT_EQ(
3491 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
3492 top_controls_height_);
3493 EXPECT_FLOAT_EQ(
3494 15.f,
3495 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3496 top_controls_height_);
3499 // Test that changing the top controls layout height is correctly applied to
3500 // the inner viewport container bounds. That is, the top controls layout
3501 // height is the amount that the inner viewport container was shrunk outside
3502 // the compositor to accommodate the top controls.
3503 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
3504 CreateHostImpl(settings_, CreateOutputSurface());
3505 SetupTopControlsAndScrollLayerWithVirtualViewport(
3506 layer_size_, layer_size_, layer_size_);
3507 DrawFrame();
3509 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
3510 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
3512 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3513 1.f);
3514 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3515 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3517 host_impl_->DidChangeTopControlsPosition();
3518 LayerImpl* inner_clip_ptr =
3519 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3520 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3521 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3523 host_impl_->sync_tree()->root_layer()->SetBounds(
3524 gfx::Size(inner_clip_ptr->bounds().width(),
3525 inner_clip_ptr->bounds().height() - 50.f));
3527 host_impl_->ActivateSyncTree();
3529 inner_clip_ptr =
3530 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3531 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3533 // The total bounds should remain unchanged since the bounds delta should
3534 // account for the difference between the layout height and the current
3535 // top controls offset.
3536 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3537 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), inner_clip_ptr->bounds_delta());
3539 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
3540 host_impl_->DidChangeTopControlsPosition();
3542 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
3543 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
3544 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
3545 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), inner_clip_ptr->bounds_delta());
3546 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
3547 inner_clip_ptr->bounds());
3550 // Test that showing/hiding the top controls when the viewport is fully scrolled
3551 // doesn't incorrectly change the viewport offset due to clamping from changing
3552 // viewport bounds.
3553 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
3554 SetupTopControlsAndScrollLayerWithVirtualViewport(
3555 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3556 DrawFrame();
3558 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3560 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
3561 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
3563 // Scroll the viewports to max scroll offset.
3564 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3565 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3567 gfx::ScrollOffset viewport_offset =
3568 host_impl_->active_tree()->TotalScrollOffset();
3569 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
3571 // Hide the top controls by 25px.
3572 gfx::Vector2dF scroll_delta(0.f, 25.f);
3573 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3574 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3575 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3577 // scrolling down at the max extents no longer hides the top controls
3578 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3580 // forcefully hide the top controls by 25px
3581 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
3582 host_impl_->ScrollEnd();
3584 EXPECT_FLOAT_EQ(scroll_delta.y(),
3585 top_controls_height_ -
3586 host_impl_->top_controls_manager()->ContentTopOffset());
3588 inner_scroll->ClampScrollToMaxScrollOffset();
3589 outer_scroll->ClampScrollToMaxScrollOffset();
3591 // We should still be fully scrolled.
3592 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3593 host_impl_->active_tree()->TotalScrollOffset());
3595 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
3597 // Bring the top controls down by 25px.
3598 scroll_delta = gfx::Vector2dF(0.f, -25.f);
3599 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3600 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3601 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3602 host_impl_->ScrollEnd();
3604 // The viewport offset shouldn't have changed.
3605 EXPECT_EQ(viewport_offset,
3606 host_impl_->active_tree()->TotalScrollOffset());
3608 // Scroll the viewports to max scroll offset.
3609 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3610 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3611 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3612 host_impl_->active_tree()->TotalScrollOffset());
3615 // Test that the top controls coming in and out maintains the same aspect ratio
3616 // between the inner and outer viewports.
3617 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
3618 SetupTopControlsAndScrollLayerWithVirtualViewport(
3619 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3620 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 2.f);
3621 DrawFrame();
3623 EXPECT_FLOAT_EQ(top_controls_height_,
3624 host_impl_->top_controls_manager()->ContentTopOffset());
3626 gfx::Vector2dF scroll_delta(0.f, 25.f);
3627 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3628 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3629 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3630 host_impl_->ScrollEnd();
3632 EXPECT_FLOAT_EQ(scroll_delta.y(),
3633 top_controls_height_ -
3634 host_impl_->top_controls_manager()->ContentTopOffset());
3636 // Top controls were hidden by 25px so the inner viewport should have expanded
3637 // by that much.
3638 LayerImpl* outer_container =
3639 host_impl_->active_tree()->OuterViewportContainerLayer();
3640 LayerImpl* inner_container =
3641 host_impl_->active_tree()->InnerViewportContainerLayer();
3642 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
3644 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3645 float aspect_ratio = inner_container->BoundsForScrolling().width() /
3646 inner_container->BoundsForScrolling().height();
3647 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
3648 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
3649 EXPECT_EQ(expected,
3650 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
3653 // Test that scrolling the outer viewport affects the top controls.
3654 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
3655 SetupTopControlsAndScrollLayerWithVirtualViewport(
3656 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3657 DrawFrame();
3659 EXPECT_EQ(top_controls_height_,
3660 host_impl_->top_controls_manager()->ContentTopOffset());
3662 // Send a gesture scroll that will scroll the outer viewport, make sure the
3663 // top controls get scrolled.
3664 gfx::Vector2dF scroll_delta(0.f, 15.f);
3665 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3666 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3667 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3668 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3669 host_impl_->CurrentlyScrollingLayer());
3670 host_impl_->ScrollEnd();
3672 EXPECT_FLOAT_EQ(scroll_delta.y(),
3673 top_controls_height_ -
3674 host_impl_->top_controls_manager()->ContentTopOffset());
3676 scroll_delta = gfx::Vector2dF(0.f, 50.f);
3677 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3678 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3679 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3681 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
3682 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3683 host_impl_->CurrentlyScrollingLayer());
3685 host_impl_->ScrollEnd();
3687 // Position the viewports such that the inner viewport will be scrolled.
3688 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
3689 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3690 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
3692 scroll_delta = gfx::Vector2dF(0.f, -65.f);
3693 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3694 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3695 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3697 EXPECT_EQ(top_controls_height_,
3698 host_impl_->top_controls_manager()->ContentTopOffset());
3699 EXPECT_FLOAT_EQ(
3700 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
3701 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
3703 host_impl_->ScrollEnd();
3706 TEST_F(LayerTreeHostImplTopControlsTest,
3707 ScrollNonScrollableRootWithTopControls) {
3708 CreateHostImpl(settings_, CreateOutputSurface());
3709 SetupTopControlsAndScrollLayerWithVirtualViewport(
3710 layer_size_, layer_size_, layer_size_);
3711 DrawFrame();
3713 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3714 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3716 host_impl_->top_controls_manager()->ScrollBegin();
3717 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
3718 host_impl_->top_controls_manager()->ScrollEnd();
3719 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3720 // Now that top controls have moved, expect the clip to resize.
3721 LayerImpl* inner_clip_ptr =
3722 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3723 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3725 host_impl_->ScrollEnd();
3727 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3728 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3730 float scroll_increment_y = -25.f;
3731 host_impl_->top_controls_manager()->ScrollBegin();
3732 host_impl_->top_controls_manager()->ScrollBy(
3733 gfx::Vector2dF(0.f, scroll_increment_y));
3734 EXPECT_FLOAT_EQ(-scroll_increment_y,
3735 host_impl_->top_controls_manager()->ContentTopOffset());
3736 // Now that top controls have moved, expect the clip to resize.
3737 EXPECT_EQ(gfx::Size(viewport_size_.width(),
3738 viewport_size_.height() + scroll_increment_y),
3739 inner_clip_ptr->bounds());
3741 host_impl_->top_controls_manager()->ScrollBy(
3742 gfx::Vector2dF(0.f, scroll_increment_y));
3743 host_impl_->top_controls_manager()->ScrollEnd();
3744 EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
3745 host_impl_->top_controls_manager()->ContentTopOffset());
3746 // Now that top controls have moved, expect the clip to resize.
3747 EXPECT_EQ(clip_size_, inner_clip_ptr->bounds());
3749 host_impl_->ScrollEnd();
3751 // Verify the layer is once-again non-scrollable.
3752 EXPECT_EQ(
3753 gfx::ScrollOffset(),
3754 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3756 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3757 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3760 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
3761 // Test the configuration where a non-composited root layer is embedded in a
3762 // scrollable outer layer.
3763 gfx::Size surface_size(10, 10);
3764 gfx::Size contents_size(20, 20);
3766 scoped_ptr<LayerImpl> content_layer =
3767 LayerImpl::Create(host_impl_->active_tree(), 1);
3768 content_layer->SetDrawsContent(true);
3769 content_layer->SetPosition(gfx::PointF());
3770 content_layer->SetBounds(contents_size);
3772 scoped_ptr<LayerImpl> scroll_clip_layer =
3773 LayerImpl::Create(host_impl_->active_tree(), 3);
3774 scroll_clip_layer->SetBounds(surface_size);
3776 scoped_ptr<LayerImpl> scroll_layer =
3777 LayerImpl::Create(host_impl_->active_tree(), 2);
3778 scroll_layer->SetScrollClipLayer(3);
3779 scroll_layer->SetBounds(contents_size);
3780 scroll_layer->SetPosition(gfx::PointF());
3781 scroll_layer->AddChild(content_layer.Pass());
3782 scroll_clip_layer->AddChild(scroll_layer.Pass());
3784 scroll_clip_layer->SetHasRenderSurface(true);
3785 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
3786 host_impl_->SetViewportSize(surface_size);
3787 DrawFrame();
3789 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3790 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3791 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3792 host_impl_->ScrollEnd();
3793 EXPECT_TRUE(did_request_redraw_);
3794 EXPECT_TRUE(did_request_commit_);
3797 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
3798 gfx::Size surface_size(10, 10);
3799 gfx::Size contents_size(20, 20);
3800 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3801 root->SetBounds(surface_size);
3802 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
3803 root->SetHasRenderSurface(true);
3804 host_impl_->active_tree()->SetRootLayer(root.Pass());
3805 host_impl_->SetViewportSize(surface_size);
3806 DrawFrame();
3808 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3809 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3810 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3811 host_impl_->ScrollEnd();
3812 EXPECT_TRUE(did_request_redraw_);
3813 EXPECT_TRUE(did_request_commit_);
3816 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
3817 gfx::Size surface_size(10, 10);
3818 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3819 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
3820 root->SetHasRenderSurface(true);
3821 host_impl_->active_tree()->SetRootLayer(root.Pass());
3822 host_impl_->SetViewportSize(surface_size);
3823 DrawFrame();
3825 // Scroll event is ignored because the input coordinate is outside the layer
3826 // boundaries.
3827 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3828 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
3829 EXPECT_FALSE(did_request_redraw_);
3830 EXPECT_FALSE(did_request_commit_);
3833 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
3834 gfx::Size surface_size(10, 10);
3835 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3836 root->SetHasRenderSurface(true);
3837 scoped_ptr<LayerImpl> child =
3838 CreateScrollableLayer(2, surface_size, root.get());
3839 host_impl_->SetViewportSize(surface_size);
3841 gfx::Transform matrix;
3842 matrix.RotateAboutXAxis(180.0);
3843 child->SetTransform(matrix);
3844 child->SetDoubleSided(false);
3846 root->AddChild(child.Pass());
3847 host_impl_->active_tree()->SetRootLayer(root.Pass());
3848 DrawFrame();
3850 // Scroll event is ignored because the scrollable layer is not facing the
3851 // viewer and there is nothing scrollable behind it.
3852 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3853 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3854 EXPECT_FALSE(did_request_redraw_);
3855 EXPECT_FALSE(did_request_commit_);
3858 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
3859 gfx::Size surface_size(10, 10);
3860 scoped_ptr<LayerImpl> clip_layer =
3861 LayerImpl::Create(host_impl_->active_tree(), 3);
3862 scoped_ptr<LayerImpl> content_layer =
3863 CreateScrollableLayer(1, surface_size, clip_layer.get());
3864 content_layer->SetShouldScrollOnMainThread(true);
3865 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
3867 // Note: we can use the same clip layer for both since both calls to
3868 // CreateScrollableLayer() use the same surface size.
3869 scoped_ptr<LayerImpl> scroll_layer =
3870 CreateScrollableLayer(2, surface_size, clip_layer.get());
3871 scroll_layer->AddChild(content_layer.Pass());
3872 clip_layer->AddChild(scroll_layer.Pass());
3873 clip_layer->SetHasRenderSurface(true);
3875 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
3876 host_impl_->SetViewportSize(surface_size);
3877 DrawFrame();
3879 // Scrolling fails because the content layer is asking to be scrolled on the
3880 // main thread.
3881 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
3882 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3885 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
3886 gfx::Size viewport_size(20, 20);
3887 float page_scale = 2.f;
3889 SetupScrollAndContentsLayers(viewport_size);
3891 // Setup the layers so that the outer viewport is scrollable.
3892 host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3893 viewport_size);
3894 host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
3895 gfx::Size(40, 40));
3896 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3897 DrawFrame();
3899 LayerImpl* root_scroll =
3900 host_impl_->active_tree()->OuterViewportScrollLayer();
3901 LayerImpl* inner_scroll =
3902 host_impl_->active_tree()->InnerViewportScrollLayer();
3903 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3905 gfx::Vector2d scroll_delta(0, 10);
3906 gfx::Vector2d expected_scroll_delta = scroll_delta;
3907 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3908 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3909 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3910 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3911 host_impl_->ScrollEnd();
3913 // Set new page scale from main thread.
3914 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
3916 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3917 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), inner_scroll->id(),
3918 expected_scroll_delta));
3920 // The scroll range should also have been updated.
3921 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3923 // The page scale delta remains constant because the impl thread did not
3924 // scale.
3925 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3928 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3929 gfx::Size viewport_size(20, 20);
3930 float page_scale = 2.f;
3932 SetupScrollAndContentsLayers(viewport_size);
3934 // Setup the layers so that the outer viewport is scrollable.
3935 host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3936 viewport_size);
3937 host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
3938 gfx::Size(40, 40));
3939 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3940 DrawFrame();
3942 LayerImpl* root_scroll =
3943 host_impl_->active_tree()->OuterViewportScrollLayer();
3944 LayerImpl* inner_scroll =
3945 host_impl_->active_tree()->InnerViewportScrollLayer();
3946 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3948 gfx::Vector2d scroll_delta(0, 10);
3949 gfx::Vector2d expected_scroll_delta = scroll_delta;
3950 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3951 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3952 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3953 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3954 host_impl_->ScrollEnd();
3956 // Set new page scale on impl thread by pinching.
3957 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3958 host_impl_->PinchGestureBegin();
3959 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3960 host_impl_->PinchGestureEnd();
3961 host_impl_->ScrollEnd();
3962 DrawOneFrame();
3964 // The scroll delta is not scaled because the main thread did not scale.
3965 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3966 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), inner_scroll->id(),
3967 expected_scroll_delta));
3969 // The scroll range should also have been updated.
3970 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3972 // The page scale delta should match the new scale on the impl side.
3973 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3976 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3977 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3978 gfx::Size surface_size(10, 10);
3979 float default_page_scale = 1.f;
3980 gfx::Transform default_page_scale_matrix;
3981 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3983 float new_page_scale = 2.f;
3984 gfx::Transform new_page_scale_matrix;
3985 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3987 // Create a normal scrollable root layer and another scrollable child layer.
3988 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3989 LayerImpl* root = host_impl_->active_tree()->root_layer();
3990 LayerImpl* child = scroll->children()[0];
3992 scoped_ptr<LayerImpl> scrollable_child_clip =
3993 LayerImpl::Create(host_impl_->active_tree(), 6);
3994 scoped_ptr<LayerImpl> scrollable_child =
3995 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3996 scrollable_child_clip->AddChild(scrollable_child.Pass());
3997 child->AddChild(scrollable_child_clip.Pass());
3998 LayerImpl* grand_child = child->children()[0];
4000 // Set new page scale on impl thread by pinching.
4001 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
4002 host_impl_->PinchGestureBegin();
4003 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
4004 host_impl_->PinchGestureEnd();
4005 host_impl_->ScrollEnd();
4006 DrawOneFrame();
4008 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
4009 // the page scale delta on the root layer is applied hierarchically.
4010 LayerTreeHostImpl::FrameData frame;
4011 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4012 host_impl_->DrawLayers(&frame);
4013 host_impl_->DidDrawAllLayers(frame);
4015 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
4016 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
4017 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
4018 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
4019 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
4020 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
4021 EXPECT_EQ(new_page_scale,
4022 grand_child->draw_transform().matrix().getDouble(0, 0));
4023 EXPECT_EQ(new_page_scale,
4024 grand_child->draw_transform().matrix().getDouble(1, 1));
4027 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
4028 SetupScrollAndContentsLayers(gfx::Size(30, 30));
4030 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
4031 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
4033 // Make the outer scroll layer scrollable.
4034 outer_scroll->SetBounds(gfx::Size(50, 50));
4036 DrawFrame();
4038 gfx::Vector2d scroll_delta(0, 10);
4039 gfx::Vector2d expected_scroll_delta(scroll_delta);
4040 gfx::ScrollOffset expected_max_scroll(outer_scroll->MaxScrollOffset());
4041 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4042 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4043 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4044 host_impl_->ScrollEnd();
4046 float page_scale = 2.f;
4047 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
4048 page_scale);
4050 DrawOneFrame();
4052 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
4053 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), inner_scroll->id(),
4054 expected_scroll_delta));
4056 // The scroll range should not have changed.
4057 EXPECT_EQ(outer_scroll->MaxScrollOffset(), expected_max_scroll);
4059 // The page scale delta remains constant because the impl thread did not
4060 // scale.
4061 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
4064 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
4065 // Scroll a child layer beyond its maximum scroll range and make sure the
4066 // parent layer is scrolled on the axis on which the child was unable to
4067 // scroll.
4068 gfx::Size surface_size(10, 10);
4069 gfx::Size content_size(20, 20);
4070 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
4071 root->SetBounds(surface_size);
4072 root->SetHasRenderSurface(true);
4073 scoped_ptr<LayerImpl> grand_child =
4074 CreateScrollableLayer(3, content_size, root.get());
4076 scoped_ptr<LayerImpl> child =
4077 CreateScrollableLayer(2, content_size, root.get());
4078 LayerImpl* grand_child_layer = grand_child.get();
4079 child->AddChild(grand_child.Pass());
4081 LayerImpl* child_layer = child.get();
4082 root->AddChild(child.Pass());
4083 host_impl_->active_tree()->SetRootLayer(root.Pass());
4084 host_impl_->active_tree()->DidBecomeActive();
4085 host_impl_->SetViewportSize(surface_size);
4086 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
4087 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
4089 DrawFrame();
4091 gfx::Vector2d scroll_delta(-8, -7);
4092 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4093 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4094 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4095 host_impl_->ScrollEnd();
4097 scoped_ptr<ScrollAndScaleSet> scroll_info =
4098 host_impl_->ProcessScrollDeltas();
4100 // The grand child should have scrolled up to its limit.
4101 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
4102 LayerImpl* grand_child = child->children()[0];
4103 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4104 gfx::Vector2d(0, -5)));
4106 // The child should have only scrolled on the other axis.
4107 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
4108 gfx::Vector2d(-3, 0)));
4112 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
4113 // Scroll a child layer beyond its maximum scroll range and make sure the
4114 // the scroll doesn't bubble up to the parent layer.
4115 gfx::Size surface_size(20, 20);
4116 gfx::Size viewport_size(10, 10);
4117 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
4118 root->SetHasRenderSurface(true);
4119 scoped_ptr<LayerImpl> root_scrolling =
4120 CreateScrollableLayer(2, surface_size, root.get());
4121 root_scrolling->SetIsContainerForFixedPositionLayers(true);
4123 scoped_ptr<LayerImpl> grand_child =
4124 CreateScrollableLayer(4, surface_size, root.get());
4126 scoped_ptr<LayerImpl> child =
4127 CreateScrollableLayer(3, surface_size, root.get());
4128 LayerImpl* grand_child_layer = grand_child.get();
4129 child->AddChild(grand_child.Pass());
4131 LayerImpl* child_layer = child.get();
4132 root_scrolling->AddChild(child.Pass());
4133 root->AddChild(root_scrolling.Pass());
4134 EXPECT_EQ(viewport_size, root->bounds());
4135 host_impl_->active_tree()->SetRootLayer(root.Pass());
4136 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
4137 Layer::INVALID_ID);
4138 host_impl_->active_tree()->DidBecomeActive();
4139 host_impl_->SetViewportSize(viewport_size);
4141 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4142 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4144 DrawFrame();
4146 gfx::Vector2d scroll_delta(0, -10);
4147 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4148 host_impl_->ScrollBegin(gfx::Point(),
4149 InputHandler::NON_BUBBLING_GESTURE));
4150 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4151 host_impl_->ScrollEnd();
4153 scoped_ptr<ScrollAndScaleSet> scroll_info =
4154 host_impl_->ProcessScrollDeltas();
4156 // The grand child should have scrolled up to its limit.
4157 LayerImpl* child =
4158 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
4159 LayerImpl* grand_child = child->children()[0];
4160 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4161 gfx::Vector2d(0, -2)));
4163 // The child should not have scrolled.
4164 ExpectNone(*scroll_info.get(), child->id());
4166 // The next time we scroll we should only scroll the parent.
4167 scroll_delta = gfx::Vector2d(0, -3);
4168 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4169 host_impl_->ScrollBegin(gfx::Point(5, 5),
4170 InputHandler::NON_BUBBLING_GESTURE));
4171 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
4172 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4173 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
4174 host_impl_->ScrollEnd();
4176 scroll_info = host_impl_->ProcessScrollDeltas();
4178 // The child should have scrolled up to its limit.
4179 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
4180 gfx::Vector2d(0, -3)));
4182 // The grand child should not have scrolled.
4183 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4184 gfx::Vector2d(0, -2)));
4186 // After scrolling the parent, another scroll on the opposite direction
4187 // should still scroll the child.
4188 scroll_delta = gfx::Vector2d(0, 7);
4189 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4190 host_impl_->ScrollBegin(gfx::Point(5, 5),
4191 InputHandler::NON_BUBBLING_GESTURE));
4192 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
4193 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4194 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
4195 host_impl_->ScrollEnd();
4197 scroll_info = host_impl_->ProcessScrollDeltas();
4199 // The grand child should have scrolled.
4200 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4201 gfx::Vector2d(0, 5)));
4203 // The child should not have scrolled.
4204 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
4205 gfx::Vector2d(0, -3)));
4207 // Scrolling should be adjusted from viewport space.
4208 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
4209 host_impl_->active_tree()->SetPageScaleOnActiveTree(2.f);
4211 scroll_delta = gfx::Vector2d(0, -2);
4212 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4213 host_impl_->ScrollBegin(gfx::Point(1, 1),
4214 InputHandler::NON_BUBBLING_GESTURE));
4215 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
4216 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4217 host_impl_->ScrollEnd();
4219 scroll_info = host_impl_->ProcessScrollDeltas();
4221 // Should have scrolled by half the amount in layer space (5 - 2/2)
4222 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
4223 gfx::Vector2d(0, 4)));
4226 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
4227 // When we try to scroll a non-scrollable child layer, the scroll delta
4228 // should be applied to one of its ancestors if possible.
4229 gfx::Size surface_size(10, 10);
4230 gfx::Size content_size(20, 20);
4231 scoped_ptr<LayerImpl> root_clip =
4232 LayerImpl::Create(host_impl_->active_tree(), 3);
4233 root_clip->SetHasRenderSurface(true);
4234 scoped_ptr<LayerImpl> root =
4235 CreateScrollableLayer(1, content_size, root_clip.get());
4236 // Make 'root' the clip layer for child: since they have the same sizes the
4237 // child will have zero max_scroll_offset and scrolls will bubble.
4238 scoped_ptr<LayerImpl> child =
4239 CreateScrollableLayer(2, content_size, root.get());
4240 child->SetIsContainerForFixedPositionLayers(true);
4241 root->SetBounds(content_size);
4243 int root_scroll_id = root->id();
4244 root->AddChild(child.Pass());
4245 root_clip->AddChild(root.Pass());
4247 host_impl_->SetViewportSize(surface_size);
4248 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4249 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
4250 Layer::INVALID_ID);
4251 host_impl_->active_tree()->DidBecomeActive();
4252 DrawFrame();
4254 gfx::Vector2d scroll_delta(0, 4);
4255 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4256 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4257 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4258 host_impl_->ScrollEnd();
4260 scoped_ptr<ScrollAndScaleSet> scroll_info =
4261 host_impl_->ProcessScrollDeltas();
4263 // Only the root scroll should have scrolled.
4264 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
4265 EXPECT_TRUE(
4266 ScrollInfoContains(*scroll_info.get(), root_scroll_id, scroll_delta));
4270 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
4271 gfx::Size surface_size(10, 10);
4272 scoped_ptr<LayerImpl> root_clip =
4273 LayerImpl::Create(host_impl_->active_tree(), 1);
4274 scoped_ptr<LayerImpl> root_scroll =
4275 CreateScrollableLayer(2, surface_size, root_clip.get());
4276 root_scroll->SetIsContainerForFixedPositionLayers(true);
4277 root_clip->SetHasRenderSurface(true);
4278 root_clip->AddChild(root_scroll.Pass());
4279 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4280 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
4281 Layer::INVALID_ID);
4282 host_impl_->active_tree()->DidBecomeActive();
4283 host_impl_->SetViewportSize(surface_size);
4285 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4286 // synchronization.
4287 DrawFrame();
4288 host_impl_->active_tree()->DetachLayerTree();
4289 scoped_ptr<LayerImpl> root_clip2 =
4290 LayerImpl::Create(host_impl_->active_tree(), 3);
4291 scoped_ptr<LayerImpl> root_scroll2 =
4292 CreateScrollableLayer(4, surface_size, root_clip2.get());
4293 root_scroll2->SetIsContainerForFixedPositionLayers(true);
4294 root_clip2->AddChild(root_scroll2.Pass());
4295 root_clip2->SetHasRenderSurface(true);
4296 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
4297 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
4298 Layer::INVALID_ID);
4299 host_impl_->active_tree()->DidBecomeActive();
4301 // Scrolling should still work even though we did not draw yet.
4302 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4303 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4306 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
4307 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4309 // Rotate the root layer 90 degrees counter-clockwise about its center.
4310 gfx::Transform rotate_transform;
4311 rotate_transform.Rotate(-90.0);
4312 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
4314 gfx::Size surface_size(50, 50);
4315 host_impl_->SetViewportSize(surface_size);
4316 DrawFrame();
4318 // Scroll to the right in screen coordinates with a gesture.
4319 gfx::Vector2d gesture_scroll_delta(10, 0);
4320 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4321 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4322 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4323 host_impl_->ScrollEnd();
4325 // The layer should have scrolled down in its local coordinates.
4326 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
4327 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4328 gfx::Vector2d(0, gesture_scroll_delta.x())));
4330 // Reset and scroll down with the wheel.
4331 scroll_layer->SetScrollDelta(gfx::Vector2dF());
4332 gfx::Vector2d wheel_scroll_delta(0, 10);
4333 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4334 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4335 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
4336 host_impl_->ScrollEnd();
4338 // The layer should have scrolled down in its local coordinates.
4339 scroll_info = host_impl_->ProcessScrollDeltas();
4340 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4341 wheel_scroll_delta));
4344 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
4345 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4346 int child_clip_layer_id = 6;
4347 int child_layer_id = 7;
4348 float child_layer_angle = -20.f;
4350 // Create a child layer that is rotated to a non-axis-aligned angle.
4351 scoped_ptr<LayerImpl> clip_layer =
4352 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
4353 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
4354 child_layer_id, scroll_layer->bounds(), clip_layer.get());
4355 gfx::Transform rotate_transform;
4356 rotate_transform.Translate(-50.0, -50.0);
4357 rotate_transform.Rotate(child_layer_angle);
4358 rotate_transform.Translate(50.0, 50.0);
4359 clip_layer->SetTransform(rotate_transform);
4361 // Only allow vertical scrolling.
4362 clip_layer->SetBounds(
4363 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
4364 // The rotation depends on the layer's transform origin, and the child layer
4365 // is a different size than the clip, so make sure the clip layer's origin
4366 // lines up over the child.
4367 clip_layer->SetTransformOrigin(gfx::Point3F(
4368 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
4369 LayerImpl* child_ptr = child.get();
4370 clip_layer->AddChild(child.Pass());
4371 scroll_layer->AddChild(clip_layer.Pass());
4373 gfx::Size surface_size(50, 50);
4374 host_impl_->SetViewportSize(surface_size);
4375 DrawFrame();
4377 // Scroll down in screen coordinates with a gesture.
4378 gfx::Vector2d gesture_scroll_delta(0, 10);
4379 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4380 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4381 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4382 host_impl_->ScrollEnd();
4384 // The child layer should have scrolled down in its local coordinates an
4385 // amount proportional to the angle between it and the input scroll delta.
4386 gfx::Vector2d expected_scroll_delta(
4387 0, gesture_scroll_delta.y() *
4388 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
4389 scoped_ptr<ScrollAndScaleSet> scroll_info =
4390 host_impl_->ProcessScrollDeltas();
4391 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4392 expected_scroll_delta));
4394 // The root scroll layer should not have scrolled, because the input delta
4395 // was close to the layer's axis of movement.
4396 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4399 // Now reset and scroll the same amount horizontally.
4400 child_ptr->SetScrollDelta(gfx::Vector2dF());
4401 gfx::Vector2d gesture_scroll_delta(10, 0);
4402 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4403 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4404 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4405 host_impl_->ScrollEnd();
4407 // The child layer should have scrolled down in its local coordinates an
4408 // amount proportional to the angle between it and the input scroll delta.
4409 gfx::Vector2d expected_scroll_delta(
4410 0, -gesture_scroll_delta.x() *
4411 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
4412 scoped_ptr<ScrollAndScaleSet> scroll_info =
4413 host_impl_->ProcessScrollDeltas();
4414 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4415 expected_scroll_delta));
4417 // The root scroll layer should have scrolled more, since the input scroll
4418 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4419 gfx::Vector2d expected_root_scroll_delta(
4420 gesture_scroll_delta.x() *
4421 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
4423 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4424 expected_root_scroll_delta));
4428 TEST_F(LayerTreeHostImplTest, ScrollPerspectiveTransformedLayer) {
4429 // When scrolling an element with perspective, the distance scrolled
4430 // depends on the point at which the scroll begins.
4431 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4432 int child_clip_layer_id = 6;
4433 int child_layer_id = 7;
4435 // Create a child layer that is rotated on its x axis, with perspective.
4436 scoped_ptr<LayerImpl> clip_layer =
4437 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
4438 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
4439 child_layer_id, scroll_layer->bounds(), clip_layer.get());
4440 LayerImpl* child_ptr = child.get();
4441 gfx::Transform perspective_transform;
4442 perspective_transform.Translate(-50.0, -50.0);
4443 perspective_transform.ApplyPerspectiveDepth(20);
4444 perspective_transform.RotateAboutXAxis(45);
4445 perspective_transform.Translate(50.0, 50.0);
4446 clip_layer->SetTransform(perspective_transform);
4448 clip_layer->SetBounds(gfx::Size(child_ptr->bounds().width() / 2,
4449 child_ptr->bounds().height() / 2));
4450 // The transform depends on the layer's transform origin, and the child layer
4451 // is a different size than the clip, so make sure the clip layer's origin
4452 // lines up over the child.
4453 clip_layer->SetTransformOrigin(gfx::Point3F(
4454 clip_layer->bounds().width(), clip_layer->bounds().height(), 0.f));
4455 clip_layer->AddChild(child.Pass());
4456 scroll_layer->AddChild(clip_layer.Pass());
4458 gfx::Size surface_size(50, 50);
4459 host_impl_->SetViewportSize(surface_size);
4461 scoped_ptr<ScrollAndScaleSet> scroll_info;
4463 gfx::Vector2d gesture_scroll_deltas[4];
4464 gesture_scroll_deltas[0] = gfx::Vector2d(4, 10);
4465 gesture_scroll_deltas[1] = gfx::Vector2d(4, 10);
4466 gesture_scroll_deltas[2] = gfx::Vector2d(10, 0);
4467 gesture_scroll_deltas[3] = gfx::Vector2d(10, 0);
4469 gfx::Vector2d expected_scroll_deltas[4];
4470 // Perspective affects the vertical delta by a different
4471 // amount depending on the vertical position of the |viewport_point|.
4472 expected_scroll_deltas[0] = gfx::Vector2d(2, 8);
4473 expected_scroll_deltas[1] = gfx::Vector2d(1, 4);
4474 // Deltas which start with the same vertical position of the
4475 // |viewport_point| are subject to identical perspective effects.
4476 expected_scroll_deltas[2] = gfx::Vector2d(4, 0);
4477 expected_scroll_deltas[3] = gfx::Vector2d(4, 0);
4479 gfx::Point viewport_point(1, 1);
4481 // Scroll in screen coordinates with a gesture. Each scroll starts
4482 // where the previous scroll ended, but the scroll position is reset
4483 // for each scroll.
4484 for (int i = 0; i < 4; ++i) {
4485 child_ptr->SetScrollDelta(gfx::Vector2dF());
4486 DrawFrame();
4487 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4488 host_impl_->ScrollBegin(viewport_point, InputHandler::GESTURE));
4489 host_impl_->ScrollBy(viewport_point, gesture_scroll_deltas[i]);
4490 viewport_point += gesture_scroll_deltas[i];
4491 host_impl_->ScrollEnd();
4493 scroll_info = host_impl_->ProcessScrollDeltas();
4494 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4495 expected_scroll_deltas[i]));
4497 // The root scroll layer should not have scrolled, because the input delta
4498 // was close to the layer's axis of movement.
4499 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4503 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
4504 LayerImpl* scroll_layer =
4505 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4507 // Scale the layer to twice its normal size.
4508 int scale = 2;
4509 gfx::Transform scale_transform;
4510 scale_transform.Scale(scale, scale);
4511 scroll_layer->SetTransform(scale_transform);
4513 gfx::Size surface_size(50, 50);
4514 host_impl_->SetViewportSize(surface_size);
4515 DrawFrame();
4517 // Scroll down in screen coordinates with a gesture.
4518 gfx::Vector2d scroll_delta(0, 10);
4519 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4520 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4521 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4522 host_impl_->ScrollEnd();
4524 // The layer should have scrolled down in its local coordinates, but half the
4525 // amount.
4526 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
4527 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4528 gfx::Vector2d(0, scroll_delta.y() / scale)));
4530 // Reset and scroll down with the wheel.
4531 scroll_layer->SetScrollDelta(gfx::Vector2dF());
4532 gfx::Vector2d wheel_scroll_delta(0, 10);
4533 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4534 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4535 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
4536 host_impl_->ScrollEnd();
4538 // It should apply the scale factor to the scroll delta for the wheel event.
4539 scroll_info = host_impl_->ProcessScrollDeltas();
4540 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4541 wheel_scroll_delta));
4544 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
4545 int width = 332;
4546 int height = 20;
4547 int scale = 3;
4548 SetupScrollAndContentsLayers(gfx::Size(width, height));
4549 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
4550 gfx::Size(width * scale - 1, height * scale));
4551 host_impl_->SetDeviceScaleFactor(scale);
4552 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4554 LayerImpl* inner_viewport_scroll_layer =
4555 host_impl_->active_tree()->InnerViewportScrollLayer();
4556 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4557 inner_viewport_scroll_layer->MaxScrollOffset());
4560 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
4561 public:
4562 TestScrollOffsetDelegate()
4563 : page_scale_factor_(0.f),
4564 min_page_scale_factor_(-1.f),
4565 max_page_scale_factor_(-1.f) {}
4567 ~TestScrollOffsetDelegate() override {}
4569 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
4570 const gfx::ScrollOffset& max_scroll_offset,
4571 const gfx::SizeF& scrollable_size,
4572 float page_scale_factor,
4573 float min_page_scale_factor,
4574 float max_page_scale_factor) override {
4575 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
4576 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
4577 last_set_scroll_offset_ = total_scroll_offset;
4578 max_scroll_offset_ = max_scroll_offset;
4579 scrollable_size_ = scrollable_size;
4580 page_scale_factor_ = page_scale_factor;
4581 min_page_scale_factor_ = min_page_scale_factor;
4582 max_page_scale_factor_ = max_page_scale_factor;
4585 gfx::ScrollOffset last_set_scroll_offset() {
4586 return last_set_scroll_offset_;
4589 gfx::ScrollOffset max_scroll_offset() const {
4590 return max_scroll_offset_;
4593 gfx::SizeF scrollable_size() const {
4594 return scrollable_size_;
4597 float page_scale_factor() const {
4598 return page_scale_factor_;
4601 float min_page_scale_factor() const {
4602 return min_page_scale_factor_;
4605 float max_page_scale_factor() const {
4606 return max_page_scale_factor_;
4609 private:
4610 gfx::ScrollOffset last_set_scroll_offset_;
4611 gfx::ScrollOffset max_scroll_offset_;
4612 gfx::SizeF scrollable_size_;
4613 float page_scale_factor_;
4614 float min_page_scale_factor_;
4615 float max_page_scale_factor_;
4618 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
4619 TestScrollOffsetDelegate scroll_delegate;
4620 host_impl_->SetViewportSize(gfx::Size(10, 20));
4621 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4622 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4623 clip_layer->SetBounds(gfx::Size(10, 20));
4625 // Setting the delegate results in the current scroll offset being set.
4626 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
4627 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4628 scroll_layer->SetScrollDelta(initial_scroll_delta);
4629 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4630 EXPECT_EQ(initial_scroll_delta.ToString(),
4631 scroll_delegate.last_set_scroll_offset().ToString());
4633 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4634 // page_scale_factor and {min|max}_page_scale_factor being set.
4635 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
4636 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
4637 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4638 EXPECT_EQ(1.f, scroll_delegate.min_page_scale_factor());
4639 EXPECT_EQ(1.f, scroll_delegate.max_page_scale_factor());
4641 // Put a page scale on the tree.
4642 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
4643 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4644 EXPECT_EQ(1.f, scroll_delegate.min_page_scale_factor());
4645 EXPECT_EQ(1.f, scroll_delegate.max_page_scale_factor());
4646 // Activation will update the delegate.
4647 host_impl_->ActivateSyncTree();
4648 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
4649 EXPECT_EQ(.5f, scroll_delegate.min_page_scale_factor());
4650 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4652 // Reset the page scale for the rest of the test.
4653 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4654 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
4655 EXPECT_EQ(.5f, scroll_delegate.min_page_scale_factor());
4656 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4658 // Animating page scale can change the root offset, so it should update the
4659 // delegate.
4660 host_impl_->Animate();
4661 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4662 EXPECT_EQ(.5f, scroll_delegate.min_page_scale_factor());
4663 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4665 // The pinch gesture doesn't put the delegate into a state where the scroll
4666 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4667 // delegate).
4668 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
4669 host_impl_->PinchGestureBegin();
4670 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
4671 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
4672 host_impl_->PinchGestureEnd();
4673 host_impl_->ScrollEnd();
4675 // Scrolling should be relative to the offset as given by the delegate.
4676 gfx::Vector2dF scroll_delta(0.f, 10.f);
4677 gfx::ScrollOffset current_offset(7.f, 8.f);
4679 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4680 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4681 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
4683 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4684 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
4685 scroll_delegate.last_set_scroll_offset());
4687 current_offset = gfx::ScrollOffset(42.f, 41.f);
4688 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
4689 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4690 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
4691 scroll_delegate.last_set_scroll_offset());
4692 host_impl_->ScrollEnd();
4693 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(gfx::ScrollOffset());
4695 // Forces a full tree synchronization and ensures that the scroll delegate
4696 // sees the correct size of the new tree.
4697 gfx::Size new_size(42, 24);
4698 host_impl_->CreatePendingTree();
4699 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
4700 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
4701 host_impl_->ActivateSyncTree();
4702 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
4704 // Un-setting the delegate should propagate the delegate's current offset to
4705 // the root scrollable layer.
4706 current_offset = gfx::ScrollOffset(13.f, 12.f);
4707 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
4708 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4710 EXPECT_EQ(current_offset.ToString(),
4711 scroll_layer->CurrentScrollOffset().ToString());
4714 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
4715 const gfx::Transform target_space_transform =
4716 layer->draw_properties().target_space_transform;
4717 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
4718 gfx::Point translated_point;
4719 target_space_transform.TransformPoint(&translated_point);
4720 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
4721 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
4724 TEST_F(LayerTreeHostImplTest,
4725 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
4726 TestScrollOffsetDelegate scroll_delegate;
4727 host_impl_->SetViewportSize(gfx::Size(10, 20));
4728 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4729 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4730 clip_layer->SetBounds(gfx::Size(10, 20));
4731 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4733 // Draw first frame to clear any pending draws and check scroll.
4734 DrawFrame();
4735 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
4736 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
4738 // Set external scroll delta on delegate and notify LayerTreeHost.
4739 gfx::ScrollOffset scroll_offset(10.f, 10.f);
4740 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(scroll_offset);
4742 // Check scroll delta reflected in layer.
4743 LayerTreeHostImpl::FrameData frame;
4744 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4745 host_impl_->DrawLayers(&frame);
4746 host_impl_->DidDrawAllLayers(frame);
4747 EXPECT_FALSE(frame.has_no_damage);
4748 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
4750 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4753 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
4754 InputHandlerScrollResult scroll_result;
4755 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4756 host_impl_->SetViewportSize(gfx::Size(50, 50));
4757 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4758 DrawFrame();
4759 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4761 // In-bounds scrolling does not affect overscroll.
4762 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4763 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4764 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4765 EXPECT_TRUE(scroll_result.did_scroll);
4766 EXPECT_FALSE(scroll_result.did_overscroll_root);
4767 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4768 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4770 // Overscroll events are reflected immediately.
4771 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4772 EXPECT_TRUE(scroll_result.did_scroll);
4773 EXPECT_TRUE(scroll_result.did_overscroll_root);
4774 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4775 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4776 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4777 host_impl_->accumulated_root_overscroll());
4779 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4780 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4781 EXPECT_TRUE(scroll_result.did_scroll);
4782 EXPECT_FALSE(scroll_result.did_overscroll_root);
4783 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4784 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4785 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4786 host_impl_->accumulated_root_overscroll());
4788 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4789 EXPECT_FALSE(scroll_result.did_scroll);
4790 EXPECT_TRUE(scroll_result.did_overscroll_root);
4791 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4792 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4793 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4794 host_impl_->accumulated_root_overscroll());
4796 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4797 EXPECT_TRUE(scroll_result.did_scroll);
4798 EXPECT_FALSE(scroll_result.did_overscroll_root);
4799 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4800 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4801 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4802 host_impl_->accumulated_root_overscroll());
4804 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4805 EXPECT_TRUE(scroll_result.did_scroll);
4806 EXPECT_TRUE(scroll_result.did_overscroll_root);
4807 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
4808 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
4809 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4810 host_impl_->accumulated_root_overscroll());
4812 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4813 EXPECT_TRUE(scroll_result.did_scroll);
4814 EXPECT_TRUE(scroll_result.did_overscroll_root);
4815 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4816 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
4817 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4818 host_impl_->accumulated_root_overscroll());
4820 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4821 EXPECT_TRUE(scroll_result.did_scroll);
4822 EXPECT_TRUE(scroll_result.did_overscroll_root);
4823 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4824 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4825 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4826 host_impl_->accumulated_root_overscroll());
4828 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4829 // as no scroll occurs.
4830 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4831 EXPECT_FALSE(scroll_result.did_scroll);
4832 EXPECT_TRUE(scroll_result.did_overscroll_root);
4833 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4834 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
4835 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4836 host_impl_->accumulated_root_overscroll());
4838 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4839 EXPECT_FALSE(scroll_result.did_scroll);
4840 EXPECT_TRUE(scroll_result.did_overscroll_root);
4841 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4842 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
4843 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4844 host_impl_->accumulated_root_overscroll());
4846 // Overscroll resets on valid scroll.
4847 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4848 EXPECT_TRUE(scroll_result.did_scroll);
4849 EXPECT_FALSE(scroll_result.did_overscroll_root);
4850 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4851 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4852 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4853 host_impl_->accumulated_root_overscroll());
4855 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4856 EXPECT_TRUE(scroll_result.did_scroll);
4857 EXPECT_TRUE(scroll_result.did_overscroll_root);
4858 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4859 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4860 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4861 host_impl_->accumulated_root_overscroll());
4863 host_impl_->ScrollEnd();
4867 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
4868 // Scroll child layers beyond their maximum scroll range and make sure root
4869 // overscroll does not accumulate.
4870 InputHandlerScrollResult scroll_result;
4871 gfx::Size surface_size(10, 10);
4872 scoped_ptr<LayerImpl> root_clip =
4873 LayerImpl::Create(host_impl_->active_tree(), 4);
4874 root_clip->SetHasRenderSurface(true);
4876 scoped_ptr<LayerImpl> root =
4877 CreateScrollableLayer(1, surface_size, root_clip.get());
4879 scoped_ptr<LayerImpl> grand_child =
4880 CreateScrollableLayer(3, surface_size, root_clip.get());
4882 scoped_ptr<LayerImpl> child =
4883 CreateScrollableLayer(2, surface_size, root_clip.get());
4884 LayerImpl* grand_child_layer = grand_child.get();
4885 child->AddChild(grand_child.Pass());
4887 LayerImpl* child_layer = child.get();
4888 root->AddChild(child.Pass());
4889 root_clip->AddChild(root.Pass());
4890 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4891 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4892 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4893 host_impl_->active_tree()->DidBecomeActive();
4894 host_impl_->SetViewportSize(surface_size);
4895 DrawFrame();
4897 gfx::Vector2d scroll_delta(0, -10);
4898 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4899 host_impl_->ScrollBegin(gfx::Point(),
4900 InputHandler::NON_BUBBLING_GESTURE));
4901 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4902 EXPECT_TRUE(scroll_result.did_scroll);
4903 EXPECT_FALSE(scroll_result.did_overscroll_root);
4904 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4905 host_impl_->ScrollEnd();
4907 // The next time we scroll we should only scroll the parent, but overscroll
4908 // should still not reach the root layer.
4909 scroll_delta = gfx::Vector2d(0, -30);
4910 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4911 host_impl_->ScrollBegin(gfx::Point(5, 5),
4912 InputHandler::NON_BUBBLING_GESTURE));
4913 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4914 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4915 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4916 EXPECT_TRUE(scroll_result.did_scroll);
4917 EXPECT_FALSE(scroll_result.did_overscroll_root);
4918 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
4919 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4920 host_impl_->ScrollEnd();
4922 // After scrolling the parent, another scroll on the opposite direction
4923 // should scroll the child.
4924 scroll_delta = gfx::Vector2d(0, 70);
4925 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4926 host_impl_->ScrollBegin(gfx::Point(5, 5),
4927 InputHandler::NON_BUBBLING_GESTURE));
4928 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4929 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4930 EXPECT_TRUE(scroll_result.did_scroll);
4931 EXPECT_FALSE(scroll_result.did_overscroll_root);
4932 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4933 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4934 host_impl_->ScrollEnd();
4938 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
4939 // When we try to scroll a non-scrollable child layer, the scroll delta
4940 // should be applied to one of its ancestors if possible. Overscroll should
4941 // be reflected only when it has bubbled up to the root scrolling layer.
4942 InputHandlerScrollResult scroll_result;
4943 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4944 DrawFrame();
4946 gfx::Vector2d scroll_delta(0, 8);
4947 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4948 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4949 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4950 EXPECT_TRUE(scroll_result.did_scroll);
4951 EXPECT_FALSE(scroll_result.did_overscroll_root);
4952 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4953 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4954 EXPECT_TRUE(scroll_result.did_scroll);
4955 EXPECT_TRUE(scroll_result.did_overscroll_root);
4956 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4957 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4958 EXPECT_FALSE(scroll_result.did_scroll);
4959 EXPECT_TRUE(scroll_result.did_overscroll_root);
4960 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4961 host_impl_->ScrollEnd();
4965 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4966 InputHandlerScrollResult scroll_result;
4967 LayerTreeSettings settings;
4968 CreateHostImpl(settings, CreateOutputSurface());
4970 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4971 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4972 clip_layer->SetBounds(gfx::Size(50, 50));
4973 host_impl_->SetViewportSize(gfx::Size(50, 50));
4974 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4975 DrawFrame();
4976 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4978 // Even though the layer can't scroll the overscroll still happens.
4979 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4980 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4981 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4982 EXPECT_FALSE(scroll_result.did_scroll);
4983 EXPECT_TRUE(scroll_result.did_overscroll_root);
4984 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4987 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4988 InputHandlerScrollResult scroll_result;
4989 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4991 DrawFrame();
4993 // Edge glow effect should be applicable only upon reaching Edges
4994 // of the content. unnecessary glow effect calls shouldn't be
4995 // called while scrolling up without reaching the edge of the content.
4996 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4997 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4998 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4999 EXPECT_TRUE(scroll_result.did_scroll);
5000 EXPECT_FALSE(scroll_result.did_overscroll_root);
5001 EXPECT_EQ(gfx::Vector2dF().ToString(),
5002 host_impl_->accumulated_root_overscroll().ToString());
5003 scroll_result =
5004 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
5005 EXPECT_TRUE(scroll_result.did_scroll);
5006 EXPECT_FALSE(scroll_result.did_overscroll_root);
5007 EXPECT_EQ(gfx::Vector2dF().ToString(),
5008 host_impl_->accumulated_root_overscroll().ToString());
5009 host_impl_->ScrollEnd();
5010 // unusedrootDelta should be subtracted from applied delta so that
5011 // unwanted glow effect calls are not called.
5012 EXPECT_EQ(InputHandler::SCROLL_STARTED,
5013 host_impl_->ScrollBegin(gfx::Point(0, 0),
5014 InputHandler::NON_BUBBLING_GESTURE));
5015 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
5016 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
5017 EXPECT_TRUE(scroll_result.did_scroll);
5018 EXPECT_TRUE(scroll_result.did_overscroll_root);
5019 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
5020 host_impl_->accumulated_root_overscroll().ToString());
5022 scroll_result =
5023 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
5024 EXPECT_FALSE(scroll_result.did_scroll);
5025 EXPECT_FALSE(scroll_result.did_overscroll_root);
5026 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
5027 host_impl_->accumulated_root_overscroll().ToString());
5028 host_impl_->ScrollEnd();
5029 // TestCase to check kEpsilon, which prevents minute values to trigger
5030 // gloweffect without reaching edge.
5031 EXPECT_EQ(InputHandler::SCROLL_STARTED,
5032 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
5033 scroll_result =
5034 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
5035 EXPECT_FALSE(scroll_result.did_scroll);
5036 EXPECT_FALSE(scroll_result.did_overscroll_root);
5037 EXPECT_EQ(gfx::Vector2dF().ToString(),
5038 host_impl_->accumulated_root_overscroll().ToString());
5039 host_impl_->ScrollEnd();
5043 class BlendStateCheckLayer : public LayerImpl {
5044 public:
5045 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
5046 int id,
5047 ResourceProvider* resource_provider) {
5048 return make_scoped_ptr(
5049 new BlendStateCheckLayer(tree_impl, id, resource_provider));
5052 void AppendQuads(RenderPass* render_pass,
5053 AppendQuadsData* append_quads_data) override {
5054 quads_appended_ = true;
5056 gfx::Rect opaque_rect;
5057 if (contents_opaque())
5058 opaque_rect = quad_rect_;
5059 else
5060 opaque_rect = opaque_content_rect_;
5061 gfx::Rect visible_quad_rect = quad_rect_;
5063 SharedQuadState* shared_quad_state =
5064 render_pass->CreateAndAppendSharedQuadState();
5065 PopulateSharedQuadState(shared_quad_state);
5067 TileDrawQuad* test_blending_draw_quad =
5068 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
5069 test_blending_draw_quad->SetNew(shared_quad_state,
5070 quad_rect_,
5071 opaque_rect,
5072 visible_quad_rect,
5073 resource_id_,
5074 gfx::RectF(0.f, 0.f, 1.f, 1.f),
5075 gfx::Size(1, 1),
5076 false,
5077 false);
5078 test_blending_draw_quad->visible_rect = quad_visible_rect_;
5079 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
5080 EXPECT_EQ(has_render_surface_, !!render_surface());
5083 void SetExpectation(bool blend, bool has_render_surface) {
5084 blend_ = blend;
5085 has_render_surface_ = has_render_surface;
5086 quads_appended_ = false;
5089 bool quads_appended() const { return quads_appended_; }
5091 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
5092 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
5093 void SetOpaqueContentRect(const gfx::Rect& rect) {
5094 opaque_content_rect_ = rect;
5097 private:
5098 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
5099 int id,
5100 ResourceProvider* resource_provider)
5101 : LayerImpl(tree_impl, id),
5102 blend_(false),
5103 has_render_surface_(false),
5104 quads_appended_(false),
5105 quad_rect_(5, 5, 5, 5),
5106 quad_visible_rect_(5, 5, 5, 5),
5107 resource_id_(resource_provider->CreateResource(
5108 gfx::Size(1, 1),
5109 GL_CLAMP_TO_EDGE,
5110 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
5111 RGBA_8888)) {
5112 resource_provider->AllocateForTesting(resource_id_);
5113 SetBounds(gfx::Size(10, 10));
5114 SetDrawsContent(true);
5117 bool blend_;
5118 bool has_render_surface_;
5119 bool quads_appended_;
5120 gfx::Rect quad_rect_;
5121 gfx::Rect opaque_content_rect_;
5122 gfx::Rect quad_visible_rect_;
5123 ResourceId resource_id_;
5126 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
5128 scoped_ptr<LayerImpl> root =
5129 LayerImpl::Create(host_impl_->active_tree(), 1);
5130 root->SetBounds(gfx::Size(10, 10));
5131 root->SetDrawsContent(false);
5132 root->SetHasRenderSurface(true);
5133 host_impl_->active_tree()->SetRootLayer(root.Pass());
5135 LayerImpl* root = host_impl_->active_tree()->root_layer();
5137 root->AddChild(
5138 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5140 host_impl_->resource_provider()));
5141 BlendStateCheckLayer* layer1 =
5142 static_cast<BlendStateCheckLayer*>(root->children()[0]);
5143 layer1->SetPosition(gfx::PointF(2.f, 2.f));
5145 LayerTreeHostImpl::FrameData frame;
5147 // Opaque layer, drawn without blending.
5148 layer1->SetContentsOpaque(true);
5149 layer1->SetExpectation(false, false);
5150 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5151 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5152 host_impl_->DrawLayers(&frame);
5153 EXPECT_TRUE(layer1->quads_appended());
5154 host_impl_->DidDrawAllLayers(frame);
5156 // Layer with translucent content and painting, so drawn with blending.
5157 layer1->SetContentsOpaque(false);
5158 layer1->SetExpectation(true, false);
5159 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5160 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5161 host_impl_->DrawLayers(&frame);
5162 EXPECT_TRUE(layer1->quads_appended());
5163 host_impl_->DidDrawAllLayers(frame);
5165 // Layer with translucent opacity, drawn with blending.
5166 layer1->SetContentsOpaque(true);
5167 layer1->SetOpacity(0.5f);
5168 layer1->SetExpectation(true, false);
5169 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5170 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5171 host_impl_->DrawLayers(&frame);
5172 EXPECT_TRUE(layer1->quads_appended());
5173 host_impl_->DidDrawAllLayers(frame);
5175 // Layer with translucent opacity and painting, drawn with blending.
5176 layer1->SetContentsOpaque(true);
5177 layer1->SetOpacity(0.5f);
5178 layer1->SetExpectation(true, false);
5179 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5180 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5181 host_impl_->DrawLayers(&frame);
5182 EXPECT_TRUE(layer1->quads_appended());
5183 host_impl_->DidDrawAllLayers(frame);
5185 layer1->AddChild(
5186 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5188 host_impl_->resource_provider()));
5189 BlendStateCheckLayer* layer2 =
5190 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
5191 layer2->SetPosition(gfx::PointF(4.f, 4.f));
5193 // 2 opaque layers, drawn without blending.
5194 layer1->SetContentsOpaque(true);
5195 layer1->SetOpacity(1.f);
5196 layer1->SetExpectation(false, false);
5197 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5198 layer2->SetContentsOpaque(true);
5199 layer2->SetOpacity(1.f);
5200 layer2->SetExpectation(false, false);
5201 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5202 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5203 host_impl_->DrawLayers(&frame);
5204 EXPECT_TRUE(layer1->quads_appended());
5205 EXPECT_TRUE(layer2->quads_appended());
5206 host_impl_->DidDrawAllLayers(frame);
5208 // Parent layer with translucent content, drawn with blending.
5209 // Child layer with opaque content, drawn without blending.
5210 layer1->SetContentsOpaque(false);
5211 layer1->SetExpectation(true, false);
5212 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5213 layer2->SetExpectation(false, false);
5214 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5215 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5216 host_impl_->DrawLayers(&frame);
5217 EXPECT_TRUE(layer1->quads_appended());
5218 EXPECT_TRUE(layer2->quads_appended());
5219 host_impl_->DidDrawAllLayers(frame);
5221 // Parent layer with translucent content but opaque painting, drawn without
5222 // blending.
5223 // Child layer with opaque content, drawn without blending.
5224 layer1->SetContentsOpaque(true);
5225 layer1->SetExpectation(false, false);
5226 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5227 layer2->SetExpectation(false, false);
5228 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5229 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5230 host_impl_->DrawLayers(&frame);
5231 EXPECT_TRUE(layer1->quads_appended());
5232 EXPECT_TRUE(layer2->quads_appended());
5233 host_impl_->DidDrawAllLayers(frame);
5235 // Parent layer with translucent opacity and opaque content. Since it has a
5236 // drawing child, it's drawn to a render surface which carries the opacity,
5237 // so it's itself drawn without blending.
5238 // Child layer with opaque content, drawn without blending (parent surface
5239 // carries the inherited opacity).
5240 layer1->SetContentsOpaque(true);
5241 layer1->SetOpacity(0.5f);
5242 layer1->SetHasRenderSurface(true);
5243 layer1->SetExpectation(false, true);
5244 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5245 layer2->SetExpectation(false, false);
5246 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5247 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5248 host_impl_->active_tree()->root_layer());
5249 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5250 host_impl_->DrawLayers(&frame);
5251 EXPECT_TRUE(layer1->quads_appended());
5252 EXPECT_TRUE(layer2->quads_appended());
5253 host_impl_->DidDrawAllLayers(frame);
5254 layer1->SetHasRenderSurface(false);
5256 // Draw again, but with child non-opaque, to make sure
5257 // layer1 not culled.
5258 layer1->SetContentsOpaque(true);
5259 layer1->SetOpacity(1.f);
5260 layer1->SetExpectation(false, false);
5261 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5262 layer2->SetContentsOpaque(true);
5263 layer2->SetOpacity(0.5f);
5264 layer2->SetExpectation(true, false);
5265 layer2->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 EXPECT_TRUE(layer2->quads_appended());
5270 host_impl_->DidDrawAllLayers(frame);
5272 // A second way of making the child non-opaque.
5273 layer1->SetContentsOpaque(true);
5274 layer1->SetOpacity(1.f);
5275 layer1->SetExpectation(false, false);
5276 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5277 layer2->SetContentsOpaque(false);
5278 layer2->SetOpacity(1.f);
5279 layer2->SetExpectation(true, false);
5280 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5281 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5282 host_impl_->DrawLayers(&frame);
5283 EXPECT_TRUE(layer1->quads_appended());
5284 EXPECT_TRUE(layer2->quads_appended());
5285 host_impl_->DidDrawAllLayers(frame);
5287 // And when the layer says its not opaque but is painted opaque, it is not
5288 // blended.
5289 layer1->SetContentsOpaque(true);
5290 layer1->SetOpacity(1.f);
5291 layer1->SetExpectation(false, false);
5292 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5293 layer2->SetContentsOpaque(true);
5294 layer2->SetOpacity(1.f);
5295 layer2->SetExpectation(false, false);
5296 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5297 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5298 host_impl_->DrawLayers(&frame);
5299 EXPECT_TRUE(layer1->quads_appended());
5300 EXPECT_TRUE(layer2->quads_appended());
5301 host_impl_->DidDrawAllLayers(frame);
5303 // Layer with partially opaque contents, drawn with blending.
5304 layer1->SetContentsOpaque(false);
5305 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5306 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5307 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5308 layer1->SetExpectation(true, false);
5309 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5310 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5311 host_impl_->DrawLayers(&frame);
5312 EXPECT_TRUE(layer1->quads_appended());
5313 host_impl_->DidDrawAllLayers(frame);
5315 // Layer with partially opaque contents partially culled, drawn with blending.
5316 layer1->SetContentsOpaque(false);
5317 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5318 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5319 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5320 layer1->SetExpectation(true, false);
5321 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5322 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5323 host_impl_->DrawLayers(&frame);
5324 EXPECT_TRUE(layer1->quads_appended());
5325 host_impl_->DidDrawAllLayers(frame);
5327 // Layer with partially opaque contents culled, drawn with blending.
5328 layer1->SetContentsOpaque(false);
5329 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5330 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5331 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5332 layer1->SetExpectation(true, false);
5333 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5334 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5335 host_impl_->DrawLayers(&frame);
5336 EXPECT_TRUE(layer1->quads_appended());
5337 host_impl_->DidDrawAllLayers(frame);
5339 // Layer with partially opaque contents and translucent contents culled, drawn
5340 // without blending.
5341 layer1->SetContentsOpaque(false);
5342 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5343 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5344 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5345 layer1->SetExpectation(false, false);
5346 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5347 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5348 host_impl_->DrawLayers(&frame);
5349 EXPECT_TRUE(layer1->quads_appended());
5350 host_impl_->DidDrawAllLayers(frame);
5353 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
5354 protected:
5355 LayerTreeHostImplViewportCoveredTest() :
5356 gutter_quad_material_(DrawQuad::SOLID_COLOR),
5357 child_(NULL),
5358 did_activate_pending_tree_(false) {}
5360 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
5361 if (always_draw) {
5362 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5364 return FakeOutputSurface::Create3d();
5367 void SetupActiveTreeLayers() {
5368 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
5369 host_impl_->active_tree()->SetRootLayer(
5370 LayerImpl::Create(host_impl_->active_tree(), 1));
5371 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
5372 host_impl_->active_tree()->root_layer()->AddChild(
5373 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5375 host_impl_->resource_provider()));
5376 child_ = static_cast<BlendStateCheckLayer*>(
5377 host_impl_->active_tree()->root_layer()->children()[0]);
5378 child_->SetExpectation(false, false);
5379 child_->SetContentsOpaque(true);
5382 // Expect no gutter rects.
5383 void TestLayerCoversFullViewport() {
5384 gfx::Rect layer_rect(viewport_size_);
5385 child_->SetPosition(layer_rect.origin());
5386 child_->SetBounds(layer_rect.size());
5387 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5388 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5390 LayerTreeHostImpl::FrameData frame;
5391 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5392 ASSERT_EQ(1u, frame.render_passes.size());
5394 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5395 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5396 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5398 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5399 host_impl_->DidDrawAllLayers(frame);
5402 // Expect fullscreen gutter rect.
5403 void TestEmptyLayer() {
5404 gfx::Rect layer_rect(0, 0, 0, 0);
5405 child_->SetPosition(layer_rect.origin());
5406 child_->SetBounds(layer_rect.size());
5407 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5408 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5410 LayerTreeHostImpl::FrameData frame;
5411 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5412 ASSERT_EQ(1u, frame.render_passes.size());
5414 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
5415 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5416 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5418 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5419 host_impl_->DidDrawAllLayers(frame);
5422 // Expect four surrounding gutter rects.
5423 void TestLayerInMiddleOfViewport() {
5424 gfx::Rect layer_rect(500, 500, 200, 200);
5425 child_->SetPosition(layer_rect.origin());
5426 child_->SetBounds(layer_rect.size());
5427 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5428 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5430 LayerTreeHostImpl::FrameData frame;
5431 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5432 ASSERT_EQ(1u, frame.render_passes.size());
5434 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
5435 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
5436 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5438 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5439 host_impl_->DidDrawAllLayers(frame);
5442 // Expect no gutter rects.
5443 void TestLayerIsLargerThanViewport() {
5444 gfx::Rect layer_rect(viewport_size_.width() + 10,
5445 viewport_size_.height() + 10);
5446 child_->SetPosition(layer_rect.origin());
5447 child_->SetBounds(layer_rect.size());
5448 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5449 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5451 LayerTreeHostImpl::FrameData frame;
5452 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5453 ASSERT_EQ(1u, frame.render_passes.size());
5455 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5456 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5457 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5459 host_impl_->DidDrawAllLayers(frame);
5462 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
5464 void set_gutter_quad_material(DrawQuad::Material material) {
5465 gutter_quad_material_ = material;
5467 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
5468 gutter_texture_size_ = gutter_texture_size;
5471 protected:
5472 size_t CountGutterQuads(const QuadList& quad_list) {
5473 size_t num_gutter_quads = 0;
5474 for (const auto& quad : quad_list) {
5475 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
5477 return num_gutter_quads;
5480 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
5481 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5482 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
5485 // Make sure that the texture coordinates match their expectations.
5486 void ValidateTextureDrawQuads(const QuadList& quad_list) {
5487 for (const auto& quad : quad_list) {
5488 if (quad->material != DrawQuad::TEXTURE_CONTENT)
5489 continue;
5490 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
5491 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
5492 gutter_texture_size_, host_impl_->device_scale_factor());
5493 EXPECT_EQ(texture_quad->uv_top_left.x(),
5494 texture_quad->rect.x() / gutter_texture_size_pixels.width());
5495 EXPECT_EQ(texture_quad->uv_top_left.y(),
5496 texture_quad->rect.y() / gutter_texture_size_pixels.height());
5497 EXPECT_EQ(
5498 texture_quad->uv_bottom_right.x(),
5499 texture_quad->rect.right() / gutter_texture_size_pixels.width());
5500 EXPECT_EQ(
5501 texture_quad->uv_bottom_right.y(),
5502 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
5506 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
5507 return gfx::ToRoundedSize(
5508 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
5511 DrawQuad::Material gutter_quad_material_;
5512 gfx::Size gutter_texture_size_;
5513 gfx::Size viewport_size_;
5514 BlendStateCheckLayer* child_;
5515 bool did_activate_pending_tree_;
5518 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
5519 viewport_size_ = gfx::Size(1000, 1000);
5521 bool always_draw = false;
5522 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5524 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5525 SetupActiveTreeLayers();
5526 TestLayerCoversFullViewport();
5527 TestEmptyLayer();
5528 TestLayerInMiddleOfViewport();
5529 TestLayerIsLargerThanViewport();
5532 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
5533 viewport_size_ = gfx::Size(1000, 1000);
5535 bool always_draw = false;
5536 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5538 host_impl_->SetDeviceScaleFactor(2.f);
5539 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5540 SetupActiveTreeLayers();
5541 TestLayerCoversFullViewport();
5542 TestEmptyLayer();
5543 TestLayerInMiddleOfViewport();
5544 TestLayerIsLargerThanViewport();
5547 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
5548 viewport_size_ = gfx::Size(1000, 1000);
5550 bool always_draw = true;
5551 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5553 // Pending tree to force active_tree size invalid. Not used otherwise.
5554 host_impl_->CreatePendingTree();
5555 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5556 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5558 SetupActiveTreeLayers();
5559 TestEmptyLayer();
5560 TestLayerInMiddleOfViewport();
5561 TestLayerIsLargerThanViewport();
5564 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
5565 viewport_size_ = gfx::Size(1000, 1000);
5567 bool always_draw = true;
5568 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5570 // Set larger viewport and activate it to active tree.
5571 host_impl_->CreatePendingTree();
5572 gfx::Size larger_viewport(viewport_size_.width() + 100,
5573 viewport_size_.height() + 100);
5574 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
5575 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5576 host_impl_->ActivateSyncTree();
5577 EXPECT_TRUE(did_activate_pending_tree_);
5578 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
5580 // Shrink pending tree viewport without activating.
5581 host_impl_->CreatePendingTree();
5582 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5583 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5585 SetupActiveTreeLayers();
5586 TestEmptyLayer();
5587 TestLayerInMiddleOfViewport();
5588 TestLayerIsLargerThanViewport();
5591 class FakeDrawableLayerImpl: public LayerImpl {
5592 public:
5593 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5594 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
5596 protected:
5597 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
5598 : LayerImpl(tree_impl, id) {}
5601 // Only reshape when we know we are going to draw. Otherwise, the reshape
5602 // can leave the window at the wrong size if we never draw and the proper
5603 // viewport size is never set.
5604 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
5605 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5606 scoped_ptr<OutputSurface> output_surface(
5607 FakeOutputSurface::Create3d(provider));
5608 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5610 scoped_ptr<LayerImpl> root =
5611 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5612 root->SetBounds(gfx::Size(10, 10));
5613 root->SetDrawsContent(true);
5614 root->SetHasRenderSurface(true);
5615 host_impl_->active_tree()->SetRootLayer(root.Pass());
5616 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
5617 provider->TestContext3d()->clear_reshape_called();
5619 LayerTreeHostImpl::FrameData frame;
5620 host_impl_->SetViewportSize(gfx::Size(10, 10));
5621 host_impl_->SetDeviceScaleFactor(1.f);
5622 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5623 host_impl_->DrawLayers(&frame);
5624 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5625 EXPECT_EQ(provider->TestContext3d()->width(), 10);
5626 EXPECT_EQ(provider->TestContext3d()->height(), 10);
5627 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5628 host_impl_->DidDrawAllLayers(frame);
5629 provider->TestContext3d()->clear_reshape_called();
5631 host_impl_->SetViewportSize(gfx::Size(20, 30));
5632 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5633 host_impl_->DrawLayers(&frame);
5634 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5635 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5636 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5637 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5638 host_impl_->DidDrawAllLayers(frame);
5639 provider->TestContext3d()->clear_reshape_called();
5641 host_impl_->SetDeviceScaleFactor(2.f);
5642 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5643 host_impl_->DrawLayers(&frame);
5644 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5645 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5646 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5647 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
5648 host_impl_->DidDrawAllLayers(frame);
5649 provider->TestContext3d()->clear_reshape_called();
5652 // Make sure damage tracking propagates all the way to the graphics context,
5653 // where it should request to swap only the sub-buffer that is damaged.
5654 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
5655 scoped_refptr<TestContextProvider> context_provider(
5656 TestContextProvider::Create());
5657 context_provider->BindToCurrentThread();
5658 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
5660 scoped_ptr<FakeOutputSurface> output_surface(
5661 FakeOutputSurface::Create3d(context_provider));
5662 FakeOutputSurface* fake_output_surface = output_surface.get();
5664 // This test creates its own LayerTreeHostImpl, so
5665 // that we can force partial swap enabled.
5666 LayerTreeSettings settings;
5667 settings.renderer_settings.partial_swap_enabled = true;
5668 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
5669 LayerTreeHostImpl::Create(
5670 settings, this, &proxy_, &stats_instrumentation_,
5671 &shared_bitmap_manager_, NULL, &task_graph_runner_, 0);
5672 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
5673 layer_tree_host_impl->WillBeginImplFrame(
5674 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5675 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
5677 scoped_ptr<LayerImpl> root =
5678 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
5679 root->SetHasRenderSurface(true);
5680 scoped_ptr<LayerImpl> child =
5681 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
5682 child->SetPosition(gfx::PointF(12.f, 13.f));
5683 child->SetBounds(gfx::Size(14, 15));
5684 child->SetDrawsContent(true);
5685 root->SetBounds(gfx::Size(500, 500));
5686 root->SetDrawsContent(true);
5687 root->AddChild(child.Pass());
5688 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
5690 LayerTreeHostImpl::FrameData frame;
5692 // First frame, the entire screen should get swapped.
5693 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5694 layer_tree_host_impl->DrawLayers(&frame);
5695 layer_tree_host_impl->DidDrawAllLayers(frame);
5696 layer_tree_host_impl->SwapBuffers(frame);
5697 gfx::Rect expected_swap_rect(0, 0, 500, 500);
5698 EXPECT_EQ(expected_swap_rect.ToString(),
5699 fake_output_surface->last_swap_rect().ToString());
5701 // Second frame, only the damaged area should get swapped. Damage should be
5702 // the union of old and new child rects.
5703 // expected damage rect: gfx::Rect(26, 28);
5704 // expected swap rect: vertically flipped, with origin at bottom left corner.
5705 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
5706 gfx::PointF());
5707 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5708 layer_tree_host_impl->DrawLayers(&frame);
5709 host_impl_->DidDrawAllLayers(frame);
5710 layer_tree_host_impl->SwapBuffers(frame);
5712 // Make sure that partial swap is constrained to the viewport dimensions
5713 // expected damage rect: gfx::Rect(500, 500);
5714 // expected swap rect: flipped damage rect, but also clamped to viewport
5715 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
5716 EXPECT_EQ(expected_swap_rect.ToString(),
5717 fake_output_surface->last_swap_rect().ToString());
5719 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
5720 // This will damage everything.
5721 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
5722 SK_ColorBLACK);
5723 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5724 layer_tree_host_impl->DrawLayers(&frame);
5725 host_impl_->DidDrawAllLayers(frame);
5726 layer_tree_host_impl->SwapBuffers(frame);
5728 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
5729 EXPECT_EQ(expected_swap_rect.ToString(),
5730 fake_output_surface->last_swap_rect().ToString());
5733 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
5734 scoped_ptr<LayerImpl> root =
5735 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5736 scoped_ptr<LayerImpl> child =
5737 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
5738 child->SetBounds(gfx::Size(10, 10));
5739 child->SetDrawsContent(true);
5740 root->SetBounds(gfx::Size(10, 10));
5741 root->SetDrawsContent(true);
5742 root->SetHasRenderSurface(true);
5743 root->AddChild(child.Pass());
5745 host_impl_->active_tree()->SetRootLayer(root.Pass());
5747 LayerTreeHostImpl::FrameData frame;
5749 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5750 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
5751 EXPECT_EQ(1u, frame.render_passes.size());
5752 host_impl_->DidDrawAllLayers(frame);
5755 class FakeLayerWithQuads : public LayerImpl {
5756 public:
5757 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5758 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
5761 void AppendQuads(RenderPass* render_pass,
5762 AppendQuadsData* append_quads_data) override {
5763 SharedQuadState* shared_quad_state =
5764 render_pass->CreateAndAppendSharedQuadState();
5765 PopulateSharedQuadState(shared_quad_state);
5767 SkColor gray = SkColorSetRGB(100, 100, 100);
5768 gfx::Rect quad_rect(bounds());
5769 gfx::Rect visible_quad_rect(quad_rect);
5770 SolidColorDrawQuad* my_quad =
5771 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5772 my_quad->SetNew(
5773 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
5776 private:
5777 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
5778 : LayerImpl(tree_impl, id) {}
5781 class MockContext : public TestWebGraphicsContext3D {
5782 public:
5783 MOCK_METHOD1(useProgram, void(GLuint program));
5784 MOCK_METHOD5(uniform4f, void(GLint location,
5785 GLfloat x,
5786 GLfloat y,
5787 GLfloat z,
5788 GLfloat w));
5789 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
5790 GLsizei count,
5791 GLboolean transpose,
5792 const GLfloat* value));
5793 MOCK_METHOD4(drawElements, void(GLenum mode,
5794 GLsizei count,
5795 GLenum type,
5796 GLintptr offset));
5797 MOCK_METHOD1(enable, void(GLenum cap));
5798 MOCK_METHOD1(disable, void(GLenum cap));
5799 MOCK_METHOD4(scissor, void(GLint x,
5800 GLint y,
5801 GLsizei width,
5802 GLsizei height));
5805 class MockContextHarness {
5806 private:
5807 MockContext* context_;
5809 public:
5810 explicit MockContextHarness(MockContext* context)
5811 : context_(context) {
5812 context_->set_have_post_sub_buffer(true);
5814 // Catch "uninteresting" calls
5815 EXPECT_CALL(*context_, useProgram(_))
5816 .Times(0);
5818 EXPECT_CALL(*context_, drawElements(_, _, _, _))
5819 .Times(0);
5821 // These are not asserted
5822 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
5823 .WillRepeatedly(Return());
5825 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
5826 .WillRepeatedly(Return());
5828 // Any un-sanctioned calls to enable() are OK
5829 EXPECT_CALL(*context_, enable(_))
5830 .WillRepeatedly(Return());
5832 // Any un-sanctioned calls to disable() are OK
5833 EXPECT_CALL(*context_, disable(_))
5834 .WillRepeatedly(Return());
5837 void MustDrawSolidQuad() {
5838 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5839 .WillOnce(Return())
5840 .RetiresOnSaturation();
5842 EXPECT_CALL(*context_, useProgram(_))
5843 .WillOnce(Return())
5844 .RetiresOnSaturation();
5847 void MustSetScissor(int x, int y, int width, int height) {
5848 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5849 .WillRepeatedly(Return());
5851 EXPECT_CALL(*context_, scissor(x, y, width, height))
5852 .Times(AtLeast(1))
5853 .WillRepeatedly(Return());
5856 void MustSetNoScissor() {
5857 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5858 .WillRepeatedly(Return());
5860 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5861 .Times(0);
5863 EXPECT_CALL(*context_, scissor(_, _, _, _))
5864 .Times(0);
5868 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5869 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5870 MockContext* mock_context = mock_context_owned.get();
5871 MockContextHarness harness(mock_context);
5873 // Run test case
5874 LayerTreeSettings settings = DefaultSettings();
5875 settings.renderer_settings.partial_swap_enabled = false;
5876 CreateHostImpl(settings,
5877 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5878 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5880 // Without partial swap, and no clipping, no scissor is set.
5881 harness.MustDrawSolidQuad();
5882 harness.MustSetNoScissor();
5884 LayerTreeHostImpl::FrameData frame;
5885 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5886 host_impl_->DrawLayers(&frame);
5887 host_impl_->DidDrawAllLayers(frame);
5889 Mock::VerifyAndClearExpectations(&mock_context);
5891 // Without partial swap, but a layer does clip its subtree, one scissor is
5892 // set.
5893 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5894 harness.MustDrawSolidQuad();
5895 harness.MustSetScissor(0, 0, 10, 10);
5897 LayerTreeHostImpl::FrameData frame;
5898 host_impl_->active_tree()->BuildPropertyTreesForTesting();
5899 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5900 host_impl_->DrawLayers(&frame);
5901 host_impl_->DidDrawAllLayers(frame);
5903 Mock::VerifyAndClearExpectations(&mock_context);
5906 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5907 scoped_ptr<MockContext> context_owned(new MockContext);
5908 MockContext* mock_context = context_owned.get();
5909 MockContextHarness harness(mock_context);
5911 LayerTreeSettings settings = DefaultSettings();
5912 settings.renderer_settings.partial_swap_enabled = true;
5913 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5914 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5916 // The first frame is not a partially-swapped one. No scissor should be set.
5917 harness.MustSetNoScissor();
5918 harness.MustDrawSolidQuad();
5920 LayerTreeHostImpl::FrameData frame;
5921 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5922 host_impl_->DrawLayers(&frame);
5923 host_impl_->DidDrawAllLayers(frame);
5925 Mock::VerifyAndClearExpectations(&mock_context);
5927 // Damage a portion of the frame.
5928 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5929 gfx::Rect(0, 0, 2, 3));
5931 // The second frame will be partially-swapped (the y coordinates are flipped).
5932 harness.MustSetScissor(0, 7, 2, 3);
5933 harness.MustDrawSolidQuad();
5935 LayerTreeHostImpl::FrameData frame;
5936 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5937 host_impl_->DrawLayers(&frame);
5938 host_impl_->DidDrawAllLayers(frame);
5940 Mock::VerifyAndClearExpectations(&mock_context);
5943 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5944 bool partial_swap,
5945 LayerTreeHostImplClient* client,
5946 Proxy* proxy,
5947 SharedBitmapManager* manager,
5948 TaskGraphRunner* task_graph_runner,
5949 RenderingStatsInstrumentation* stats_instrumentation) {
5950 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5951 scoped_ptr<OutputSurface> output_surface(
5952 FakeOutputSurface::Create3d(provider));
5953 provider->BindToCurrentThread();
5954 provider->TestContext3d()->set_have_post_sub_buffer(true);
5956 LayerTreeSettings settings;
5957 settings.renderer_settings.partial_swap_enabled = partial_swap;
5958 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5959 LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation,
5960 manager, nullptr, task_graph_runner, 0);
5961 my_host_impl->InitializeRenderer(output_surface.Pass());
5962 my_host_impl->WillBeginImplFrame(
5963 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5964 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5967 Layers are created as follows:
5969 +--------------------+
5970 | 1 |
5971 | +-----------+ |
5972 | | 2 | |
5973 | | +-------------------+
5974 | | | 3 |
5975 | | +-------------------+
5976 | | | |
5977 | +-----------+ |
5980 +--------------------+
5982 Layers 1, 2 have render surfaces
5984 scoped_ptr<LayerImpl> root =
5985 LayerImpl::Create(my_host_impl->active_tree(), 1);
5986 scoped_ptr<LayerImpl> child =
5987 LayerImpl::Create(my_host_impl->active_tree(), 2);
5988 scoped_ptr<LayerImpl> grand_child =
5989 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5991 gfx::Rect root_rect(0, 0, 100, 100);
5992 gfx::Rect child_rect(10, 10, 50, 50);
5993 gfx::Rect grand_child_rect(5, 5, 150, 150);
5995 root->SetHasRenderSurface(true);
5996 root->SetPosition(root_rect.origin());
5997 root->SetBounds(root_rect.size());
5998 root->draw_properties().visible_layer_rect = root_rect;
5999 root->SetDrawsContent(false);
6000 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
6002 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
6003 child->SetOpacity(0.5f);
6004 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
6005 child->draw_properties().visible_layer_rect = child_rect;
6006 child->SetDrawsContent(false);
6007 child->SetHasRenderSurface(true);
6009 grand_child->SetPosition(grand_child_rect.origin());
6010 grand_child->SetBounds(grand_child_rect.size());
6011 grand_child->draw_properties().visible_layer_rect = grand_child_rect;
6012 grand_child->SetDrawsContent(true);
6014 child->AddChild(grand_child.Pass());
6015 root->AddChild(child.Pass());
6017 my_host_impl->active_tree()->SetRootLayer(root.Pass());
6018 return my_host_impl.Pass();
6021 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
6022 TestSharedBitmapManager shared_bitmap_manager;
6023 TestTaskGraphRunner task_graph_runner;
6024 scoped_ptr<LayerTreeHostImpl> my_host_impl =
6025 SetupLayersForOpacity(true, this, &proxy_, &shared_bitmap_manager,
6026 &task_graph_runner, &stats_instrumentation_);
6028 LayerTreeHostImpl::FrameData frame;
6029 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
6031 // Verify all quads have been computed
6032 ASSERT_EQ(2U, frame.render_passes.size());
6033 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
6034 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
6035 EXPECT_EQ(DrawQuad::SOLID_COLOR,
6036 frame.render_passes[0]->quad_list.front()->material);
6037 EXPECT_EQ(DrawQuad::RENDER_PASS,
6038 frame.render_passes[1]->quad_list.front()->material);
6040 my_host_impl->DrawLayers(&frame);
6041 my_host_impl->DidDrawAllLayers(frame);
6045 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
6046 TestSharedBitmapManager shared_bitmap_manager;
6047 TestTaskGraphRunner task_graph_runner;
6048 scoped_ptr<LayerTreeHostImpl> my_host_impl =
6049 SetupLayersForOpacity(false, this, &proxy_, &shared_bitmap_manager,
6050 &task_graph_runner, &stats_instrumentation_);
6052 LayerTreeHostImpl::FrameData frame;
6053 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
6055 // Verify all quads have been computed
6056 ASSERT_EQ(2U, frame.render_passes.size());
6057 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
6058 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
6059 EXPECT_EQ(DrawQuad::SOLID_COLOR,
6060 frame.render_passes[0]->quad_list.front()->material);
6061 EXPECT_EQ(DrawQuad::RENDER_PASS,
6062 frame.render_passes[1]->quad_list.front()->material);
6064 my_host_impl->DrawLayers(&frame);
6065 my_host_impl->DidDrawAllLayers(frame);
6069 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
6070 scoped_ptr<TestWebGraphicsContext3D> context =
6071 TestWebGraphicsContext3D::Create();
6072 TestWebGraphicsContext3D* context3d = context.get();
6073 scoped_ptr<OutputSurface> output_surface(
6074 FakeOutputSurface::Create3d(context.Pass()));
6075 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6077 scoped_ptr<LayerImpl> root_layer =
6078 LayerImpl::Create(host_impl_->active_tree(), 1);
6079 root_layer->SetBounds(gfx::Size(10, 10));
6080 root_layer->SetHasRenderSurface(true);
6082 scoped_refptr<VideoFrame> softwareFrame =
6083 media::VideoFrame::CreateColorFrame(
6084 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
6085 FakeVideoFrameProvider provider;
6086 provider.set_frame(softwareFrame);
6087 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6088 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
6089 video_layer->SetBounds(gfx::Size(10, 10));
6090 video_layer->SetDrawsContent(true);
6091 root_layer->AddChild(video_layer.Pass());
6093 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
6094 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
6095 io_surface_layer->SetBounds(gfx::Size(10, 10));
6096 io_surface_layer->SetDrawsContent(true);
6097 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
6098 root_layer->AddChild(io_surface_layer.Pass());
6100 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
6102 EXPECT_EQ(0u, context3d->NumTextures());
6104 LayerTreeHostImpl::FrameData frame;
6105 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6106 host_impl_->DrawLayers(&frame);
6107 host_impl_->DidDrawAllLayers(frame);
6108 host_impl_->SwapBuffers(frame);
6110 EXPECT_GT(context3d->NumTextures(), 0u);
6112 // Kill the layer tree.
6113 host_impl_->active_tree()->SetRootLayer(
6114 LayerImpl::Create(host_impl_->active_tree(), 100));
6115 // There should be no textures left in use after.
6116 EXPECT_EQ(0u, context3d->NumTextures());
6119 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
6120 public:
6121 MOCK_METHOD1(useProgram, void(GLuint program));
6122 MOCK_METHOD4(drawElements, void(GLenum mode,
6123 GLsizei count,
6124 GLenum type,
6125 GLintptr offset));
6128 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
6129 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
6130 new MockDrawQuadsToFillScreenContext);
6131 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
6133 // Run test case
6134 LayerTreeSettings settings = DefaultSettings();
6135 settings.renderer_settings.partial_swap_enabled = false;
6136 CreateHostImpl(settings,
6137 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
6138 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6139 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
6141 // Verify one quad is drawn when transparent background set is not set.
6142 host_impl_->active_tree()->set_has_transparent_background(false);
6143 EXPECT_CALL(*mock_context, useProgram(_))
6144 .Times(1);
6145 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
6146 .Times(1);
6147 LayerTreeHostImpl::FrameData frame;
6148 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6149 host_impl_->DrawLayers(&frame);
6150 host_impl_->DidDrawAllLayers(frame);
6151 Mock::VerifyAndClearExpectations(&mock_context);
6153 // Verify no quads are drawn when transparent background is set.
6154 host_impl_->active_tree()->set_has_transparent_background(true);
6155 host_impl_->SetFullRootLayerDamage();
6156 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6157 host_impl_->DrawLayers(&frame);
6158 host_impl_->DidDrawAllLayers(frame);
6159 Mock::VerifyAndClearExpectations(&mock_context);
6162 class LayerTreeHostImplTestWithDelegatingRenderer
6163 : public LayerTreeHostImplTest {
6164 protected:
6165 scoped_ptr<OutputSurface> CreateOutputSurface() override {
6166 return FakeOutputSurface::CreateDelegating3d();
6169 void DrawFrameAndTestDamage(const gfx::Rect& expected_damage) {
6170 bool expect_to_draw = !expected_damage.IsEmpty();
6172 LayerTreeHostImpl::FrameData frame;
6173 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6175 if (!expect_to_draw) {
6176 // With no damage, we don't draw, and no quads are created.
6177 ASSERT_EQ(0u, frame.render_passes.size());
6178 } else {
6179 ASSERT_EQ(1u, frame.render_passes.size());
6181 // Verify the damage rect for the root render pass.
6182 const RenderPass* root_render_pass = frame.render_passes.back();
6183 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
6185 // Verify the root and child layers' quads are generated and not being
6186 // culled.
6187 ASSERT_EQ(2u, root_render_pass->quad_list.size());
6189 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
6190 gfx::Rect expected_child_visible_rect(child->bounds());
6191 EXPECT_EQ(expected_child_visible_rect,
6192 root_render_pass->quad_list.front()->visible_rect);
6194 LayerImpl* root = host_impl_->active_tree()->root_layer();
6195 gfx::Rect expected_root_visible_rect(root->bounds());
6196 EXPECT_EQ(expected_root_visible_rect,
6197 root_render_pass->quad_list.ElementAt(1)->visible_rect);
6200 host_impl_->DrawLayers(&frame);
6201 host_impl_->DidDrawAllLayers(frame);
6202 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
6206 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
6207 scoped_ptr<SolidColorLayerImpl> root =
6208 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6209 root->SetPosition(gfx::PointF());
6210 root->SetBounds(gfx::Size(10, 10));
6211 root->SetDrawsContent(true);
6212 root->SetHasRenderSurface(true);
6214 // Child layer is in the bottom right corner.
6215 scoped_ptr<SolidColorLayerImpl> child =
6216 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
6217 child->SetPosition(gfx::PointF(9.f, 9.f));
6218 child->SetBounds(gfx::Size(1, 1));
6219 child->SetDrawsContent(true);
6220 root->AddChild(child.Pass());
6222 host_impl_->active_tree()->SetRootLayer(root.Pass());
6224 // Draw a frame. In the first frame, the entire viewport should be damaged.
6225 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6226 DrawFrameAndTestDamage(full_frame_damage);
6228 // The second frame has damage that doesn't touch the child layer. Its quads
6229 // should still be generated.
6230 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
6231 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
6232 DrawFrameAndTestDamage(small_damage);
6234 // The third frame should have no damage, so no quads should be generated.
6235 gfx::Rect no_damage;
6236 DrawFrameAndTestDamage(no_damage);
6239 // TODO(reveman): Remove this test and the ability to prevent on demand raster
6240 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
6241 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
6242 LayerTreeSettings settings;
6243 CreateHostImpl(settings, CreateOutputSurface());
6244 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
6247 class FakeMaskLayerImpl : public LayerImpl {
6248 public:
6249 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
6250 int id) {
6251 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
6254 void GetContentsResourceId(ResourceId* resource_id,
6255 gfx::Size* resource_size) const override {
6256 *resource_id = 0;
6259 private:
6260 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
6261 : LayerImpl(tree_impl, id) {}
6264 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
6265 public:
6266 using GLRenderer::ShouldAntialiasQuad;
6269 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
6270 // Due to precision issues (especially on Android), sometimes far
6271 // away quads can end up thinking they need AA.
6272 float device_scale_factor = 4.f / 3.f;
6273 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6274 gfx::Size root_size(2000, 1000);
6275 gfx::Size device_viewport_size =
6276 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
6277 host_impl_->SetViewportSize(device_viewport_size);
6279 host_impl_->CreatePendingTree();
6280 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
6281 16.f);
6283 scoped_ptr<LayerImpl> scoped_root =
6284 LayerImpl::Create(host_impl_->pending_tree(), 1);
6285 LayerImpl* root = scoped_root.get();
6286 root->SetHasRenderSurface(true);
6288 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
6290 scoped_ptr<LayerImpl> scoped_scrolling_layer =
6291 LayerImpl::Create(host_impl_->pending_tree(), 2);
6292 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
6293 root->AddChild(scoped_scrolling_layer.Pass());
6295 gfx::Size content_layer_bounds(100000, 100);
6296 gfx::Size pile_tile_size(3000, 3000);
6297 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
6298 pile_tile_size, content_layer_bounds));
6300 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
6301 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
6302 3, pile);
6303 LayerImpl* content_layer = scoped_content_layer.get();
6304 scrolling_layer->AddChild(scoped_content_layer.Pass());
6305 content_layer->SetBounds(content_layer_bounds);
6306 content_layer->SetDrawsContent(true);
6308 root->SetBounds(root_size);
6310 gfx::ScrollOffset scroll_offset(100000, 0);
6311 scrolling_layer->SetScrollClipLayer(root->id());
6312 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
6314 host_impl_->ActivateSyncTree();
6316 bool update_lcd_text = false;
6317 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
6318 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6320 LayerTreeHostImpl::FrameData frame;
6321 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6323 ASSERT_EQ(1u, frame.render_passes.size());
6324 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
6325 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
6327 bool clipped = false, force_aa = false;
6328 gfx::QuadF device_layer_quad = MathUtil::MapQuad(
6329 quad->shared_quad_state->quad_to_target_transform,
6330 gfx::QuadF(gfx::RectF(quad->shared_quad_state->visible_quad_layer_rect)),
6331 &clipped);
6332 EXPECT_FALSE(clipped);
6333 bool antialiased =
6334 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6335 device_layer_quad, clipped, force_aa);
6336 EXPECT_FALSE(antialiased);
6338 host_impl_->DrawLayers(&frame);
6339 host_impl_->DidDrawAllLayers(frame);
6343 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
6344 public:
6345 CompositorFrameMetadataTest()
6346 : swap_buffers_complete_(0) {}
6348 void DidSwapBuffersCompleteOnImplThread() override {
6349 swap_buffers_complete_++;
6352 int swap_buffers_complete_;
6355 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
6356 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
6358 LayerTreeHostImpl::FrameData frame;
6359 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6360 host_impl_->DrawLayers(&frame);
6361 host_impl_->DidDrawAllLayers(frame);
6363 CompositorFrameAck ack;
6364 host_impl_->ReclaimResources(&ack);
6365 host_impl_->DidSwapBuffersComplete();
6366 EXPECT_EQ(swap_buffers_complete_, 1);
6369 class CountingSoftwareDevice : public SoftwareOutputDevice {
6370 public:
6371 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6373 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
6374 ++frames_began_;
6375 return SoftwareOutputDevice::BeginPaint(damage_rect);
6377 void EndPaint() override {
6378 SoftwareOutputDevice::EndPaint();
6379 ++frames_ended_;
6382 int frames_began_, frames_ended_;
6385 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
6386 // No main thread evictions in resourceless software mode.
6387 set_reduce_memory_result(false);
6388 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
6389 EXPECT_TRUE(CreateHostImpl(
6390 DefaultSettings(),
6391 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device))));
6392 host_impl_->SetViewportSize(gfx::Size(50, 50));
6394 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6396 const gfx::Transform external_transform;
6397 const gfx::Rect external_viewport;
6398 const gfx::Rect external_clip;
6399 const bool resourceless_software_draw = true;
6400 host_impl_->SetExternalDrawConstraints(external_transform,
6401 external_viewport,
6402 external_clip,
6403 external_viewport,
6404 external_transform,
6405 resourceless_software_draw);
6407 EXPECT_EQ(0, software_device->frames_began_);
6408 EXPECT_EQ(0, software_device->frames_ended_);
6410 DrawFrame();
6412 EXPECT_EQ(1, software_device->frames_began_);
6413 EXPECT_EQ(1, software_device->frames_ended_);
6415 // Call another API method that is likely to hit nullptr in this mode.
6416 scoped_refptr<base::trace_event::TracedValue> state =
6417 make_scoped_refptr(new base::trace_event::TracedValue());
6418 host_impl_->ActivationStateAsValueInto(state.get());
6421 TEST_F(LayerTreeHostImplTest,
6422 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
6423 set_reduce_memory_result(false);
6424 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6425 FakeOutputSurface::CreateSoftware(
6426 make_scoped_ptr(new CountingSoftwareDevice))));
6428 const gfx::Transform external_transform;
6429 const gfx::Rect external_viewport;
6430 const gfx::Rect external_clip;
6431 const bool resourceless_software_draw = true;
6432 host_impl_->SetExternalDrawConstraints(external_transform,
6433 external_viewport,
6434 external_clip,
6435 external_viewport,
6436 external_transform,
6437 resourceless_software_draw);
6439 // SolidColorLayerImpl will be drawn.
6440 scoped_ptr<SolidColorLayerImpl> root_layer =
6441 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6443 // VideoLayerImpl will not be drawn.
6444 FakeVideoFrameProvider provider;
6445 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6446 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
6447 video_layer->SetBounds(gfx::Size(10, 10));
6448 video_layer->SetDrawsContent(true);
6449 root_layer->AddChild(video_layer.Pass());
6450 SetupRootLayerImpl(root_layer.Pass());
6452 LayerTreeHostImpl::FrameData frame;
6453 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6454 host_impl_->DrawLayers(&frame);
6455 host_impl_->DidDrawAllLayers(frame);
6457 EXPECT_EQ(1u, frame.will_draw_layers.size());
6458 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
6461 // Checks that we have a non-0 default allocation if we pass a context that
6462 // doesn't support memory management extensions.
6463 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
6464 LayerTreeSettings settings;
6465 host_impl_ = LayerTreeHostImpl::Create(
6466 settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_,
6467 &gpu_memory_buffer_manager_, &task_graph_runner_, 0);
6469 scoped_ptr<OutputSurface> output_surface(
6470 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6471 host_impl_->InitializeRenderer(output_surface.Pass());
6472 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
6475 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6476 ASSERT_TRUE(host_impl_->active_tree());
6478 // RequiresHighResToDraw is set when new output surface is used.
6479 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6481 host_impl_->ResetRequiresHighResToDraw();
6483 host_impl_->SetVisible(false);
6484 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6485 host_impl_->SetVisible(true);
6486 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6487 host_impl_->SetVisible(false);
6488 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6490 host_impl_->ResetRequiresHighResToDraw();
6492 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6493 host_impl_->SetVisible(true);
6494 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6497 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6498 ASSERT_TRUE(host_impl_->active_tree());
6499 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6501 // RequiresHighResToDraw is set when new output surface is used.
6502 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6504 host_impl_->ResetRequiresHighResToDraw();
6506 host_impl_->SetContentIsSuitableForGpuRasterization(true);
6507 host_impl_->SetHasGpuRasterizationTrigger(false);
6508 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6509 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6510 host_impl_->SetHasGpuRasterizationTrigger(true);
6511 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6512 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6513 host_impl_->SetHasGpuRasterizationTrigger(false);
6514 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6515 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6517 host_impl_->ResetRequiresHighResToDraw();
6519 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6520 host_impl_->SetHasGpuRasterizationTrigger(true);
6521 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6522 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6525 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
6526 public:
6527 void SetUp() override {
6528 fake_host_impl_ =
6529 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_,
6530 &shared_bitmap_manager_, &task_graph_runner_);
6531 host_impl_.reset(fake_host_impl_);
6532 host_impl_->InitializeRenderer(CreateOutputSurface());
6533 host_impl_->SetViewportSize(gfx::Size(10, 10));
6536 FakeLayerTreeHostImpl* fake_host_impl_;
6539 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6540 fake_host_impl_->DidModifyTilePriorities();
6541 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6542 fake_host_impl_->SetVisible(false);
6543 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6546 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6547 scoped_ptr<TestWebGraphicsContext3D> context =
6548 TestWebGraphicsContext3D::Create();
6549 TestWebGraphicsContext3D* context3d = context.get();
6550 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6551 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6553 EXPECT_EQ(0u, context3d->NumTextures());
6555 UIResourceId ui_resource_id = 1;
6556 bool is_opaque = false;
6557 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6558 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6559 EXPECT_EQ(1u, context3d->NumTextures());
6560 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6561 EXPECT_NE(0u, id1);
6563 // Multiple requests with the same id is allowed. The previous texture is
6564 // deleted.
6565 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6566 EXPECT_EQ(1u, context3d->NumTextures());
6567 ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6568 EXPECT_NE(0u, id2);
6569 EXPECT_NE(id1, id2);
6571 // Deleting invalid UIResourceId is allowed and does not change state.
6572 host_impl_->DeleteUIResource(-1);
6573 EXPECT_EQ(1u, context3d->NumTextures());
6575 // Should return zero for invalid UIResourceId. Number of textures should
6576 // not change.
6577 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6578 EXPECT_EQ(1u, context3d->NumTextures());
6580 host_impl_->DeleteUIResource(ui_resource_id);
6581 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6582 EXPECT_EQ(0u, context3d->NumTextures());
6584 // Should not change state for multiple deletion on one UIResourceId
6585 host_impl_->DeleteUIResource(ui_resource_id);
6586 EXPECT_EQ(0u, context3d->NumTextures());
6589 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6590 scoped_ptr<TestWebGraphicsContext3D> context =
6591 TestWebGraphicsContext3D::Create();
6592 TestWebGraphicsContext3D* context3d = context.get();
6593 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6595 EXPECT_EQ(0u, context3d->NumTextures());
6597 gfx::Size size(4, 4);
6598 // SkImageInfo has no support for ETC1. The |info| below contains the right
6599 // total pixel size for the bitmap but not the right height and width. The
6600 // correct width/height are passed directly to UIResourceBitmap.
6601 SkImageInfo info =
6602 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6603 skia::RefPtr<SkPixelRef> pixel_ref =
6604 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6605 pixel_ref->setImmutable();
6606 UIResourceBitmap bitmap(pixel_ref, size);
6607 UIResourceId ui_resource_id = 1;
6608 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6609 EXPECT_EQ(1u, context3d->NumTextures());
6610 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6611 EXPECT_NE(0u, id1);
6614 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6617 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6618 scoped_refptr<TestContextProvider> context_provider =
6619 TestContextProvider::Create();
6621 CreateHostImpl(DefaultSettings(),
6622 FakeOutputSurface::Create3d(context_provider));
6624 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6626 ScopedPtrVector<CopyOutputRequest> requests;
6627 requests.push_back(CopyOutputRequest::CreateRequest(
6628 base::Bind(&ShutdownReleasesContext_Callback)));
6630 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6632 LayerTreeHostImpl::FrameData frame;
6633 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6634 host_impl_->DrawLayers(&frame);
6635 host_impl_->DidDrawAllLayers(frame);
6637 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6638 // texture in a texture mailbox.
6639 EXPECT_FALSE(context_provider->HasOneRef());
6640 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6642 host_impl_ = nullptr;
6644 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6645 // released, and the texture deleted.
6646 EXPECT_TRUE(context_provider->HasOneRef());
6647 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6650 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6651 // When flinging via touch, only the child should scroll (we should not
6652 // bubble).
6653 gfx::Size surface_size(10, 10);
6654 gfx::Size content_size(20, 20);
6655 scoped_ptr<LayerImpl> root_clip =
6656 LayerImpl::Create(host_impl_->active_tree(), 3);
6657 root_clip->SetHasRenderSurface(true);
6659 scoped_ptr<LayerImpl> root =
6660 CreateScrollableLayer(1, content_size, root_clip.get());
6661 root->SetIsContainerForFixedPositionLayers(true);
6662 scoped_ptr<LayerImpl> child =
6663 CreateScrollableLayer(2, content_size, root_clip.get());
6665 root->AddChild(child.Pass());
6666 int root_id = root->id();
6667 root_clip->AddChild(root.Pass());
6669 host_impl_->SetViewportSize(surface_size);
6670 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6671 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6672 Layer::INVALID_ID);
6673 host_impl_->active_tree()->DidBecomeActive();
6674 DrawFrame();
6676 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6677 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6679 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6681 gfx::Vector2d scroll_delta(0, 100);
6682 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6683 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6685 host_impl_->ScrollEnd();
6687 scoped_ptr<ScrollAndScaleSet> scroll_info =
6688 host_impl_->ProcessScrollDeltas();
6690 // Only the child should have scrolled.
6691 ASSERT_EQ(1u, scroll_info->scrolls.size());
6692 ExpectNone(*scroll_info.get(), root_id);
6696 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6697 // Scroll a child layer beyond its maximum scroll range and make sure the
6698 // the scroll doesn't bubble up to the parent layer.
6699 gfx::Size surface_size(10, 10);
6700 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6701 root->SetHasRenderSurface(true);
6702 scoped_ptr<LayerImpl> root_scrolling =
6703 CreateScrollableLayer(2, surface_size, root.get());
6705 scoped_ptr<LayerImpl> grand_child =
6706 CreateScrollableLayer(4, surface_size, root.get());
6707 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6709 scoped_ptr<LayerImpl> child =
6710 CreateScrollableLayer(3, surface_size, root.get());
6711 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6712 child->AddChild(grand_child.Pass());
6714 root_scrolling->AddChild(child.Pass());
6715 root->AddChild(root_scrolling.Pass());
6716 host_impl_->active_tree()->SetRootLayer(root.Pass());
6717 host_impl_->active_tree()->DidBecomeActive();
6718 host_impl_->SetViewportSize(surface_size);
6719 DrawFrame();
6721 scoped_ptr<ScrollAndScaleSet> scroll_info;
6722 LayerImpl* child =
6723 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6724 LayerImpl* grand_child = child->children()[0];
6726 gfx::Vector2d scroll_delta(0, -2);
6727 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6728 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6729 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6731 // The grand child should have scrolled up to its limit.
6732 scroll_info = host_impl_->ProcessScrollDeltas();
6733 ASSERT_EQ(1u, scroll_info->scrolls.size());
6734 EXPECT_TRUE(
6735 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6736 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6738 // The child should have received the bubbled delta, but the locked
6739 // scrolling layer should remain set as the grand child.
6740 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6741 scroll_info = host_impl_->ProcessScrollDeltas();
6742 ASSERT_EQ(2u, scroll_info->scrolls.size());
6743 EXPECT_TRUE(
6744 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6745 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(), scroll_delta));
6746 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6748 // The first |ScrollBy| after the fling should re-lock the scrolling
6749 // layer to the first layer that scrolled, which is the child.
6750 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6751 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6752 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6754 // The child should have scrolled up to its limit.
6755 scroll_info = host_impl_->ProcessScrollDeltas();
6756 ASSERT_EQ(2u, scroll_info->scrolls.size());
6757 EXPECT_TRUE(
6758 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6759 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(),
6760 scroll_delta + scroll_delta));
6762 // As the locked layer is at it's limit, no further scrolling can occur.
6763 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6764 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6765 host_impl_->ScrollEnd();
6769 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6770 // When flinging via wheel, the root should eventually scroll (we should
6771 // bubble).
6772 gfx::Size surface_size(10, 10);
6773 gfx::Size content_size(20, 20);
6774 scoped_ptr<LayerImpl> root_clip =
6775 LayerImpl::Create(host_impl_->active_tree(), 3);
6776 root_clip->SetHasRenderSurface(true);
6777 scoped_ptr<LayerImpl> root_scroll =
6778 CreateScrollableLayer(1, content_size, root_clip.get());
6779 int root_scroll_id = root_scroll->id();
6780 scoped_ptr<LayerImpl> child =
6781 CreateScrollableLayer(2, content_size, root_clip.get());
6783 root_scroll->AddChild(child.Pass());
6784 root_clip->AddChild(root_scroll.Pass());
6786 host_impl_->SetViewportSize(surface_size);
6787 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6788 host_impl_->active_tree()->DidBecomeActive();
6789 DrawFrame();
6791 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6792 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6794 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6796 gfx::Vector2d scroll_delta(0, 100);
6797 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6798 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6800 host_impl_->ScrollEnd();
6802 scoped_ptr<ScrollAndScaleSet> scroll_info =
6803 host_impl_->ProcessScrollDeltas();
6805 // The root should have scrolled.
6806 ASSERT_EQ(2u, scroll_info->scrolls.size());
6807 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll_id,
6808 gfx::Vector2d(0, 10)));
6812 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6813 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6814 // we should return SCROLL_UNKNOWN.
6815 gfx::Size content_size(100, 100);
6816 SetupScrollAndContentsLayers(content_size);
6818 int scroll_layer_id = 2;
6819 LayerImpl* scroll_layer =
6820 host_impl_->active_tree()->LayerById(scroll_layer_id);
6821 scroll_layer->SetDrawsContent(true);
6823 int page_scale_layer_id = 5;
6824 LayerImpl* page_scale_layer =
6825 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6827 int occluder_layer_id = 6;
6828 scoped_ptr<LayerImpl> occluder_layer =
6829 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6830 occluder_layer->SetDrawsContent(true);
6831 occluder_layer->SetBounds(content_size);
6832 occluder_layer->SetPosition(gfx::PointF());
6834 // The parent of the occluder is *above* the scroller.
6835 page_scale_layer->AddChild(occluder_layer.Pass());
6837 DrawFrame();
6839 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6840 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6843 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6844 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6845 // is not the first scroller we encounter when walking up from the layer, we
6846 // should also return SCROLL_UNKNOWN.
6847 gfx::Size content_size(100, 100);
6848 SetupScrollAndContentsLayers(content_size);
6850 int scroll_layer_id = 2;
6851 LayerImpl* scroll_layer =
6852 host_impl_->active_tree()->LayerById(scroll_layer_id);
6853 scroll_layer->SetDrawsContent(true);
6855 int occluder_layer_id = 6;
6856 scoped_ptr<LayerImpl> occluder_layer =
6857 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6858 occluder_layer->SetDrawsContent(true);
6859 occluder_layer->SetBounds(content_size);
6860 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6862 int child_scroll_clip_layer_id = 7;
6863 scoped_ptr<LayerImpl> child_scroll_clip =
6864 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6866 int child_scroll_layer_id = 8;
6867 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6868 child_scroll_layer_id, content_size, child_scroll_clip.get());
6870 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6872 child_scroll->AddChild(occluder_layer.Pass());
6873 scroll_layer->AddChild(child_scroll.Pass());
6875 DrawFrame();
6877 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6878 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6881 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
6882 gfx::Size content_size(100, 100);
6883 SetupScrollAndContentsLayers(content_size);
6885 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6887 int scroll_layer_id = 2;
6888 LayerImpl* scroll_layer =
6889 host_impl_->active_tree()->LayerById(scroll_layer_id);
6891 int child_scroll_layer_id = 7;
6892 scoped_ptr<LayerImpl> child_scroll =
6893 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6894 child_scroll->SetDrawsContent(false);
6896 scroll_layer->AddChild(child_scroll.Pass());
6898 DrawFrame();
6900 // We should not have scrolled |child_scroll| even though we technically "hit"
6901 // it. The reason for this is that if the scrolling the scroll would not move
6902 // any layer that is a drawn RSLL member, then we can ignore the hit.
6904 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6905 // started scrolling the inner viewport.
6906 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6907 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6909 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6912 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
6913 gfx::Size content_size(100, 100);
6914 SetupScrollAndContentsLayers(content_size);
6916 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6917 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
6919 scoped_ptr<LayerImpl> invisible_scroll_layer =
6920 CreateScrollableLayer(7, content_size, root);
6921 invisible_scroll_layer->SetDrawsContent(false);
6923 scoped_ptr<LayerImpl> child_layer =
6924 LayerImpl::Create(host_impl_->active_tree(), 8);
6925 child_layer->SetDrawsContent(false);
6927 scoped_ptr<LayerImpl> grand_child_layer =
6928 LayerImpl::Create(host_impl_->active_tree(), 9);
6929 grand_child_layer->SetDrawsContent(true);
6930 grand_child_layer->SetBounds(content_size);
6931 // Move the grand child so it's not hit by our test point.
6932 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
6934 child_layer->AddChild(grand_child_layer.Pass());
6935 invisible_scroll_layer->AddChild(child_layer.Pass());
6936 root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
6938 DrawFrame();
6940 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6941 // a descendant which is a drawn RSLL member.
6942 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6943 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6945 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6948 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6949 // This test case is very similar to the one above with one key difference:
6950 // the invisible scroller has a scroll child that is indeed draw contents.
6951 // If we attempt to initiate a gesture scroll off of the visible scroll child
6952 // we should still start the scroll child.
6953 gfx::Size content_size(100, 100);
6954 SetupScrollAndContentsLayers(content_size);
6956 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6958 int scroll_layer_id = 2;
6959 LayerImpl* scroll_layer =
6960 host_impl_->active_tree()->LayerById(scroll_layer_id);
6962 int scroll_child_id = 6;
6963 scoped_ptr<LayerImpl> scroll_child =
6964 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6965 scroll_child->SetDrawsContent(true);
6966 scroll_child->SetBounds(content_size);
6967 // Move the scroll child so it's not hit by our test point.
6968 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6970 int invisible_scroll_layer_id = 7;
6971 scoped_ptr<LayerImpl> invisible_scroll =
6972 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6973 invisible_scroll->SetDrawsContent(false);
6975 int container_id = 8;
6976 scoped_ptr<LayerImpl> container =
6977 LayerImpl::Create(host_impl_->active_tree(), container_id);
6979 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6980 scroll_children->insert(scroll_child.get());
6981 invisible_scroll->SetScrollChildren(scroll_children.release());
6983 scroll_child->SetScrollParent(invisible_scroll.get());
6985 container->AddChild(invisible_scroll.Pass());
6986 container->AddChild(scroll_child.Pass());
6988 scroll_layer->AddChild(container.Pass());
6990 DrawFrame();
6992 // We should have scrolled |child_scroll| even though it is invisible.
6993 // The reason for this is that if the scrolling the scroll would move a layer
6994 // that is a drawn RSLL member, then we should accept this hit.
6995 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6996 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6998 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
7001 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
7002 // to CompositorFrameMetadata after SwapBuffers();
7003 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
7004 scoped_ptr<SolidColorLayerImpl> root =
7005 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
7006 root->SetPosition(gfx::PointF());
7007 root->SetBounds(gfx::Size(10, 10));
7008 root->SetDrawsContent(true);
7009 root->SetHasRenderSurface(true);
7011 host_impl_->active_tree()->SetRootLayer(root.Pass());
7013 FakeOutputSurface* fake_output_surface =
7014 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
7016 const std::vector<ui::LatencyInfo>& metadata_latency_before =
7017 fake_output_surface->last_sent_frame().metadata.latency_info;
7018 EXPECT_TRUE(metadata_latency_before.empty());
7020 ui::LatencyInfo latency_info;
7021 latency_info.AddLatencyNumber(
7022 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
7023 scoped_ptr<SwapPromise> swap_promise(
7024 new LatencyInfoSwapPromise(latency_info));
7025 host_impl_->active_tree()->QueuePinnedSwapPromise(swap_promise.Pass());
7026 host_impl_->SetNeedsRedraw();
7028 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7029 LayerTreeHostImpl::FrameData frame;
7030 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7031 host_impl_->DrawLayers(&frame);
7032 host_impl_->DidDrawAllLayers(frame);
7033 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7035 const std::vector<ui::LatencyInfo>& metadata_latency_after =
7036 fake_output_surface->last_sent_frame().metadata.latency_info;
7037 EXPECT_EQ(1u, metadata_latency_after.size());
7038 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
7039 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
7042 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
7043 int root_layer_id = 1;
7044 scoped_ptr<SolidColorLayerImpl> root =
7045 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
7046 root->SetPosition(gfx::PointF());
7047 root->SetBounds(gfx::Size(10, 10));
7048 root->SetDrawsContent(true);
7049 root->SetHasRenderSurface(true);
7051 host_impl_->active_tree()->SetRootLayer(root.Pass());
7053 // Ensure the default frame selection bounds are empty.
7054 FakeOutputSurface* fake_output_surface =
7055 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
7056 const ViewportSelection& selection_before =
7057 fake_output_surface->last_sent_frame().metadata.selection;
7058 EXPECT_EQ(ViewportSelectionBound(), selection_before.start);
7059 EXPECT_EQ(ViewportSelectionBound(), selection_before.end);
7061 // Plumb the layer-local selection bounds.
7062 gfx::PointF selection_top(5, 0);
7063 gfx::PointF selection_bottom(5, 5);
7064 LayerSelection selection;
7065 selection.start.type = SELECTION_BOUND_CENTER;
7066 selection.start.layer_id = root_layer_id;
7067 selection.start.edge_bottom = selection_bottom;
7068 selection.start.edge_top = selection_top;
7069 selection.end = selection.start;
7070 host_impl_->active_tree()->RegisterSelection(selection);
7072 // Trigger a draw-swap sequence.
7073 host_impl_->SetNeedsRedraw();
7075 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
7076 LayerTreeHostImpl::FrameData frame;
7077 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
7078 host_impl_->DrawLayers(&frame);
7079 host_impl_->DidDrawAllLayers(frame);
7080 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
7082 // Ensure the selection bounds have propagated to the frame metadata.
7083 const ViewportSelection& selection_after =
7084 fake_output_surface->last_sent_frame().metadata.selection;
7085 EXPECT_EQ(selection.start.type, selection_after.start.type);
7086 EXPECT_EQ(selection.end.type, selection_after.end.type);
7087 EXPECT_EQ(selection_bottom, selection_after.start.edge_bottom);
7088 EXPECT_EQ(selection_top, selection_after.start.edge_top);
7089 EXPECT_TRUE(selection_after.start.visible);
7090 EXPECT_TRUE(selection_after.start.visible);
7093 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
7094 public:
7095 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
7096 LayerTreeHostImpl* layer_tree_host_impl,
7097 int* set_needs_commit_count,
7098 int* set_needs_redraw_count,
7099 int* forward_to_main_count)
7100 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
7101 set_needs_commit_count_(set_needs_commit_count),
7102 set_needs_redraw_count_(set_needs_redraw_count),
7103 forward_to_main_count_(forward_to_main_count) {}
7105 ~SimpleSwapPromiseMonitor() override {}
7107 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
7109 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
7111 void OnForwardScrollUpdateToMainThreadOnImpl() override {
7112 (*forward_to_main_count_)++;
7115 private:
7116 int* set_needs_commit_count_;
7117 int* set_needs_redraw_count_;
7118 int* forward_to_main_count_;
7121 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
7122 int set_needs_commit_count = 0;
7123 int set_needs_redraw_count = 0;
7124 int forward_to_main_count = 0;
7127 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7128 new SimpleSwapPromiseMonitor(NULL,
7129 host_impl_.get(),
7130 &set_needs_commit_count,
7131 &set_needs_redraw_count,
7132 &forward_to_main_count));
7133 host_impl_->SetNeedsRedraw();
7134 EXPECT_EQ(0, set_needs_commit_count);
7135 EXPECT_EQ(1, set_needs_redraw_count);
7136 EXPECT_EQ(0, forward_to_main_count);
7139 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7140 // monitored.
7141 host_impl_->SetNeedsRedraw();
7142 EXPECT_EQ(0, set_needs_commit_count);
7143 EXPECT_EQ(1, set_needs_redraw_count);
7144 EXPECT_EQ(0, forward_to_main_count);
7147 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7148 new SimpleSwapPromiseMonitor(NULL,
7149 host_impl_.get(),
7150 &set_needs_commit_count,
7151 &set_needs_redraw_count,
7152 &forward_to_main_count));
7153 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
7154 EXPECT_EQ(0, set_needs_commit_count);
7155 EXPECT_EQ(2, set_needs_redraw_count);
7156 EXPECT_EQ(0, forward_to_main_count);
7160 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7161 new SimpleSwapPromiseMonitor(NULL,
7162 host_impl_.get(),
7163 &set_needs_commit_count,
7164 &set_needs_redraw_count,
7165 &forward_to_main_count));
7166 // Empty damage rect won't signal the monitor.
7167 host_impl_->SetNeedsRedrawRect(gfx::Rect());
7168 EXPECT_EQ(0, set_needs_commit_count);
7169 EXPECT_EQ(2, set_needs_redraw_count);
7170 EXPECT_EQ(0, forward_to_main_count);
7174 set_needs_commit_count = 0;
7175 set_needs_redraw_count = 0;
7176 forward_to_main_count = 0;
7177 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
7178 new SimpleSwapPromiseMonitor(NULL,
7179 host_impl_.get(),
7180 &set_needs_commit_count,
7181 &set_needs_redraw_count,
7182 &forward_to_main_count));
7183 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7185 // Scrolling normally should not trigger any forwarding.
7186 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7187 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7188 EXPECT_TRUE(
7189 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7190 host_impl_->ScrollEnd();
7192 EXPECT_EQ(0, set_needs_commit_count);
7193 EXPECT_EQ(1, set_needs_redraw_count);
7194 EXPECT_EQ(0, forward_to_main_count);
7196 // Scrolling with a scroll handler should defer the swap to the main
7197 // thread.
7198 scroll_layer->SetHaveScrollEventHandlers(true);
7199 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7200 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7201 EXPECT_TRUE(
7202 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
7203 host_impl_->ScrollEnd();
7205 EXPECT_EQ(0, set_needs_commit_count);
7206 EXPECT_EQ(2, set_needs_redraw_count);
7207 EXPECT_EQ(1, forward_to_main_count);
7211 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
7212 public:
7213 void SetUp() override {
7214 LayerTreeSettings settings = DefaultSettings();
7215 CreateHostImpl(settings, CreateOutputSurface());
7216 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
7217 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
7218 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
7221 protected:
7222 static const int top_controls_height_;
7225 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
7227 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
7228 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7229 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7230 BeginFrameArgs begin_frame_args =
7231 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
7232 host_impl_->WillBeginImplFrame(begin_frame_args);
7233 host_impl_->Animate();
7234 EXPECT_FALSE(did_request_redraw_);
7235 host_impl_->DidFinishImplFrame();
7238 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
7239 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7240 EXPECT_FALSE(did_request_redraw_);
7241 host_impl_->CreatePendingTree();
7242 host_impl_->sync_tree()->set_top_controls_height(100);
7243 host_impl_->ActivateSyncTree();
7244 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
7247 TEST_F(LayerTreeHostImplWithTopControlsTest,
7248 TopControlsStayFullyVisibleOnHeightChange) {
7249 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7250 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7252 host_impl_->CreatePendingTree();
7253 host_impl_->sync_tree()->set_top_controls_height(0);
7254 host_impl_->ActivateSyncTree();
7255 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7257 host_impl_->CreatePendingTree();
7258 host_impl_->sync_tree()->set_top_controls_height(50);
7259 host_impl_->ActivateSyncTree();
7260 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7263 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
7264 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7265 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7266 host_impl_->DidChangeTopControlsPosition();
7267 EXPECT_TRUE(did_request_animate_);
7268 EXPECT_TRUE(did_request_redraw_);
7271 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
7272 InputHandlerScrollResult result;
7273 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7274 host_impl_->SetViewportSize(gfx::Size(100, 100));
7275 host_impl_->top_controls_manager()->UpdateTopControlsState(
7276 BOTH, SHOWN, false);
7277 DrawFrame();
7279 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7280 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7281 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7282 EXPECT_EQ(gfx::Vector2dF().ToString(),
7283 scroll_layer->CurrentScrollOffset().ToString());
7285 // Scroll just the top controls and verify that the scroll succeeds.
7286 const float residue = 10;
7287 float offset = top_controls_height_ - residue;
7288 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7289 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7290 EXPECT_TRUE(result.did_scroll);
7291 EXPECT_FLOAT_EQ(-offset,
7292 host_impl_->top_controls_manager()->ControlsTopOffset());
7293 EXPECT_EQ(gfx::Vector2dF().ToString(),
7294 scroll_layer->CurrentScrollOffset().ToString());
7296 // Scroll across the boundary
7297 const float content_scroll = 20;
7298 offset = residue + content_scroll;
7299 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7300 EXPECT_TRUE(result.did_scroll);
7301 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7302 EXPECT_EQ(-top_controls_height_,
7303 host_impl_->top_controls_manager()->ControlsTopOffset());
7304 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
7305 scroll_layer->CurrentScrollOffset().ToString());
7307 // Now scroll back to the top of the content
7308 offset = -content_scroll;
7309 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7310 EXPECT_TRUE(result.did_scroll);
7311 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7312 EXPECT_EQ(-top_controls_height_,
7313 host_impl_->top_controls_manager()->ControlsTopOffset());
7314 EXPECT_EQ(gfx::Vector2dF().ToString(),
7315 scroll_layer->CurrentScrollOffset().ToString());
7317 // And scroll the top controls completely into view
7318 offset = -top_controls_height_;
7319 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7320 EXPECT_TRUE(result.did_scroll);
7321 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7322 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7323 EXPECT_EQ(gfx::Vector2dF().ToString(),
7324 scroll_layer->CurrentScrollOffset().ToString());
7326 // And attempt to scroll past the end
7327 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7328 EXPECT_FALSE(result.did_scroll);
7329 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50));
7330 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7331 EXPECT_EQ(gfx::Vector2dF().ToString(),
7332 scroll_layer->CurrentScrollOffset().ToString());
7334 host_impl_->ScrollEnd();
7337 TEST_F(LayerTreeHostImplWithTopControlsTest, WheelUnhandledByTopControls) {
7338 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7339 host_impl_->SetViewportSize(gfx::Size(50, 100));
7340 host_impl_->active_tree()->set_top_controls_shrink_blink_size(true);
7341 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7342 false);
7343 DrawFrame();
7345 LayerImpl* viewport_layer = host_impl_->InnerViewportScrollLayer();
7347 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7348 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7349 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7350 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer->CurrentScrollOffset());
7352 // Wheel scrolls should not affect the top controls, and should pass
7353 // directly through to the viewport.
7354 const float delta = top_controls_height_;
7355 EXPECT_TRUE(
7356 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
7357 EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7358 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta),
7359 viewport_layer->CurrentScrollOffset());
7361 EXPECT_TRUE(
7362 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
7363 EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7364 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta * 2),
7365 viewport_layer->CurrentScrollOffset());
7368 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
7369 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7370 host_impl_->SetViewportSize(gfx::Size(100, 200));
7371 host_impl_->top_controls_manager()->UpdateTopControlsState(
7372 BOTH, SHOWN, false);
7373 DrawFrame();
7375 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7376 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7377 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7378 EXPECT_EQ(gfx::Vector2dF().ToString(),
7379 scroll_layer->CurrentScrollOffset().ToString());
7381 // Scroll the top controls partially.
7382 const float residue = 35;
7383 float offset = top_controls_height_ - residue;
7384 EXPECT_TRUE(
7385 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7386 EXPECT_FLOAT_EQ(-offset,
7387 host_impl_->top_controls_manager()->ControlsTopOffset());
7388 EXPECT_EQ(gfx::Vector2dF().ToString(),
7389 scroll_layer->CurrentScrollOffset().ToString());
7391 did_request_redraw_ = false;
7392 did_request_animate_ = false;
7393 did_request_commit_ = false;
7395 // End the scroll while the controls are still offset from their limit.
7396 host_impl_->ScrollEnd();
7397 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7398 EXPECT_TRUE(did_request_animate_);
7399 EXPECT_TRUE(did_request_redraw_);
7400 EXPECT_FALSE(did_request_commit_);
7402 // The top controls should properly animate until finished, despite the scroll
7403 // offset being at the origin.
7404 BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
7405 BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
7406 while (did_request_animate_) {
7407 did_request_redraw_ = false;
7408 did_request_animate_ = false;
7409 did_request_commit_ = false;
7411 float old_offset =
7412 host_impl_->top_controls_manager()->ControlsTopOffset();
7414 begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
7415 host_impl_->WillBeginImplFrame(begin_frame_args);
7416 host_impl_->Animate();
7417 EXPECT_EQ(gfx::Vector2dF().ToString(),
7418 scroll_layer->CurrentScrollOffset().ToString());
7420 float new_offset =
7421 host_impl_->top_controls_manager()->ControlsTopOffset();
7423 // No commit is needed as the controls are animating the content offset,
7424 // not the scroll offset.
7425 EXPECT_FALSE(did_request_commit_);
7427 if (new_offset != old_offset)
7428 EXPECT_TRUE(did_request_redraw_);
7430 if (new_offset != 0) {
7431 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
7432 EXPECT_TRUE(did_request_animate_);
7434 host_impl_->DidFinishImplFrame();
7436 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7439 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
7440 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7441 host_impl_->SetViewportSize(gfx::Size(100, 100));
7442 host_impl_->top_controls_manager()->UpdateTopControlsState(
7443 BOTH, SHOWN, false);
7444 float initial_scroll_offset = 50;
7445 scroll_layer->PushScrollOffsetFromMainThread(
7446 gfx::ScrollOffset(0, initial_scroll_offset));
7447 DrawFrame();
7449 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7450 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7451 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7452 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7453 scroll_layer->CurrentScrollOffset().ToString());
7455 // Scroll the top controls partially.
7456 const float residue = 15;
7457 float offset = top_controls_height_ - residue;
7458 EXPECT_TRUE(
7459 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7460 EXPECT_FLOAT_EQ(-offset,
7461 host_impl_->top_controls_manager()->ControlsTopOffset());
7462 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7463 scroll_layer->CurrentScrollOffset().ToString());
7465 did_request_redraw_ = false;
7466 did_request_animate_ = false;
7467 did_request_commit_ = false;
7469 // End the scroll while the controls are still offset from the limit.
7470 host_impl_->ScrollEnd();
7471 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7472 EXPECT_TRUE(did_request_animate_);
7473 EXPECT_TRUE(did_request_redraw_);
7474 EXPECT_FALSE(did_request_commit_);
7476 // Animate the top controls to the limit.
7477 BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
7478 BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
7479 while (did_request_animate_) {
7480 did_request_redraw_ = false;
7481 did_request_animate_ = false;
7482 did_request_commit_ = false;
7484 float old_offset =
7485 host_impl_->top_controls_manager()->ControlsTopOffset();
7487 begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
7488 host_impl_->WillBeginImplFrame(begin_frame_args);
7489 host_impl_->Animate();
7491 float new_offset =
7492 host_impl_->top_controls_manager()->ControlsTopOffset();
7494 if (new_offset != old_offset) {
7495 EXPECT_TRUE(did_request_redraw_);
7496 EXPECT_TRUE(did_request_commit_);
7498 host_impl_->DidFinishImplFrame();
7500 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7501 EXPECT_EQ(-top_controls_height_,
7502 host_impl_->top_controls_manager()->ControlsTopOffset());
7505 TEST_F(LayerTreeHostImplWithTopControlsTest,
7506 TopControlsAnimationAfterMainThreadFlingStopped) {
7507 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7508 host_impl_->SetViewportSize(gfx::Size(100, 100));
7509 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7510 false);
7511 float initial_scroll_offset = 50;
7512 scroll_layer->PushScrollOffsetFromMainThread(
7513 gfx::ScrollOffset(0, initial_scroll_offset));
7514 DrawFrame();
7516 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7517 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7518 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7519 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7520 scroll_layer->CurrentScrollOffset().ToString());
7522 // Scroll the top controls partially.
7523 const float residue = 15;
7524 float offset = top_controls_height_ - residue;
7525 EXPECT_TRUE(
7526 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7527 EXPECT_FLOAT_EQ(-offset,
7528 host_impl_->top_controls_manager()->ControlsTopOffset());
7529 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7530 scroll_layer->CurrentScrollOffset().ToString());
7532 did_request_redraw_ = false;
7533 did_request_animate_ = false;
7534 did_request_commit_ = false;
7536 // End the fling while the controls are still offset from the limit.
7537 host_impl_->MainThreadHasStoppedFlinging();
7538 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7539 EXPECT_TRUE(did_request_animate_);
7540 EXPECT_TRUE(did_request_redraw_);
7541 EXPECT_FALSE(did_request_commit_);
7543 // Animate the top controls to the limit.
7544 BeginFrameArgs begin_frame_args = CreateBeginFrameArgsForTesting(
7545 BEGINFRAME_FROM_HERE, base::TimeTicks::Now());
7546 while (did_request_animate_) {
7547 did_request_redraw_ = false;
7548 did_request_animate_ = false;
7549 did_request_commit_ = false;
7551 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7553 begin_frame_args.frame_time += base::TimeDelta::FromMilliseconds(5);
7554 host_impl_->WillBeginImplFrame(begin_frame_args);
7555 host_impl_->Animate();
7557 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7559 if (new_offset != old_offset) {
7560 EXPECT_TRUE(did_request_redraw_);
7561 EXPECT_TRUE(did_request_commit_);
7563 host_impl_->DidFinishImplFrame();
7565 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7566 EXPECT_EQ(-top_controls_height_,
7567 host_impl_->top_controls_manager()->ControlsTopOffset());
7570 TEST_F(LayerTreeHostImplWithTopControlsTest,
7571 TopControlsScrollDeltaInOverScroll) {
7572 // Verifies that the overscroll delta should not have accumulated in
7573 // the top controls if we do a hide and show without releasing finger.
7575 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7576 host_impl_->SetViewportSize(gfx::Size(100, 100));
7577 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7578 false);
7579 DrawFrame();
7581 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7582 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7583 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7585 float offset = 50;
7586 EXPECT_TRUE(
7587 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7588 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7589 EXPECT_EQ(gfx::Vector2dF().ToString(),
7590 scroll_layer->CurrentScrollOffset().ToString());
7592 EXPECT_TRUE(
7593 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7594 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7595 scroll_layer->CurrentScrollOffset().ToString());
7597 EXPECT_TRUE(
7598 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7600 // Should have fully scrolled
7601 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7602 scroll_layer->CurrentScrollOffset().ToString());
7604 float overscrollamount = 10;
7606 // Overscroll the content
7607 EXPECT_FALSE(
7608 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7609 .did_scroll);
7610 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7611 scroll_layer->CurrentScrollOffset().ToString());
7612 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7613 host_impl_->accumulated_root_overscroll().ToString());
7615 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7616 .did_scroll);
7617 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7618 scroll_layer->CurrentScrollOffset().ToString());
7619 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7621 EXPECT_TRUE(
7622 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7623 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7624 scroll_layer->CurrentScrollOffset().ToString());
7626 // Top controls should be fully visible
7627 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7629 host_impl_->ScrollEnd();
7632 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7633 public:
7634 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7635 const gfx::Size& outer_viewport,
7636 const gfx::Size& inner_viewport) {
7637 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7638 const int kOuterViewportClipLayerId = 6;
7639 const int kOuterViewportScrollLayerId = 7;
7640 const int kInnerViewportScrollLayerId = 2;
7641 const int kInnerViewportClipLayerId = 4;
7642 const int kPageScaleLayerId = 5;
7644 scoped_ptr<LayerImpl> inner_scroll =
7645 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7646 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7647 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7649 scoped_ptr<LayerImpl> inner_clip =
7650 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7651 inner_clip->SetBounds(inner_viewport);
7653 scoped_ptr<LayerImpl> page_scale =
7654 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7656 inner_scroll->SetScrollClipLayer(inner_clip->id());
7657 inner_scroll->SetBounds(outer_viewport);
7658 inner_scroll->SetPosition(gfx::PointF());
7660 scoped_ptr<LayerImpl> outer_clip =
7661 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7662 outer_clip->SetBounds(outer_viewport);
7663 outer_clip->SetIsContainerForFixedPositionLayers(true);
7665 scoped_ptr<LayerImpl> outer_scroll =
7666 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7667 outer_scroll->SetScrollClipLayer(outer_clip->id());
7668 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7669 outer_scroll->SetBounds(content_size);
7670 outer_scroll->SetPosition(gfx::PointF());
7672 scoped_ptr<LayerImpl> contents =
7673 LayerImpl::Create(layer_tree_impl, 8);
7674 contents->SetDrawsContent(true);
7675 contents->SetBounds(content_size);
7676 contents->SetPosition(gfx::PointF());
7678 outer_scroll->AddChild(contents.Pass());
7679 outer_clip->AddChild(outer_scroll.Pass());
7680 inner_scroll->AddChild(outer_clip.Pass());
7681 page_scale->AddChild(inner_scroll.Pass());
7682 inner_clip->AddChild(page_scale.Pass());
7684 inner_clip->SetHasRenderSurface(true);
7685 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7686 layer_tree_impl->SetViewportLayersFromIds(
7687 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7688 kOuterViewportScrollLayerId);
7690 host_impl_->active_tree()->DidBecomeActive();
7694 TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
7695 gfx::Size content_size = gfx::Size(100, 160);
7696 gfx::Size outer_viewport = gfx::Size(50, 80);
7697 gfx::Size inner_viewport = gfx::Size(25, 40);
7699 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7701 TestScrollOffsetDelegate scroll_delegate;
7702 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
7704 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7705 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7706 DrawFrame();
7708 gfx::ScrollOffset inner_expected;
7709 gfx::ScrollOffset outer_expected;
7710 EXPECT_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7711 EXPECT_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7713 gfx::ScrollOffset current_offset(70.f, 100.f);
7715 host_impl_->OnRootLayerDelegatedScrollOffsetChanged(current_offset);
7716 EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
7717 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
7719 // Outer viewport scrolls first. Then the rest is applied to the inner
7720 // viewport.
7721 EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f),
7722 inner_scroll->CurrentScrollOffset());
7723 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f),
7724 outer_scroll->CurrentScrollOffset());
7728 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7729 gfx::Size content_size = gfx::Size(200, 320);
7730 gfx::Size outer_viewport = gfx::Size(100, 160);
7731 gfx::Size inner_viewport = gfx::Size(50, 80);
7733 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7735 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7736 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7737 DrawFrame();
7739 gfx::Vector2dF inner_expected;
7740 gfx::Vector2dF outer_expected;
7741 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7742 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7744 // Scrolling the viewport always sets the outer scroll layer as the
7745 // currently scrolling layer.
7746 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7747 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7748 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7749 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7750 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7752 gfx::Vector2d scroll_delta(inner_viewport.width() / 2.f,
7753 inner_viewport.height() / 2.f);
7754 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7755 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7756 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), outer_scroll);
7758 host_impl_->ScrollEnd();
7759 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7761 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7762 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7764 // Fling past the inner viewport boundry, make sure outer viewport scrolls.
7765 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7766 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7767 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7768 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7769 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7771 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7772 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7773 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7775 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7776 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7777 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7779 host_impl_->ScrollEnd();
7780 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7782 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7783 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7787 TEST_F(LayerTreeHostImplVirtualViewportTest,
7788 DiagonalScrollBubblesPerfectlyToInner) {
7789 gfx::Size content_size = gfx::Size(200, 320);
7790 gfx::Size outer_viewport = gfx::Size(100, 160);
7791 gfx::Size inner_viewport = gfx::Size(50, 80);
7793 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7795 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7796 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7797 DrawFrame();
7799 gfx::Vector2dF inner_expected;
7800 gfx::Vector2dF outer_expected;
7801 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7802 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7804 // Make sure the scroll goes to the inner viewport first.
7805 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7806 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7807 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7808 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7809 InputHandler::GESTURE));
7811 // Scroll near the edge of the outer viewport.
7812 gfx::Vector2d scroll_delta(inner_viewport.width() / 2.f,
7813 inner_viewport.height() / 2.f);
7814 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7815 inner_expected += scroll_delta;
7816 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7817 InputHandler::GESTURE));
7819 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7820 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7822 // Now diagonal scroll across the outer viewport boundary in a single event.
7823 // The entirety of the scroll should be consumed, as bubbling between inner
7824 // and outer viewport layers is perfect.
7825 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7826 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7827 InputHandler::GESTURE));
7828 outer_expected += scroll_delta;
7829 inner_expected += scroll_delta;
7830 host_impl_->ScrollEnd();
7831 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7832 gfx::Point(), InputHandler::GESTURE));
7834 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7835 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7839 TEST_F(LayerTreeHostImplVirtualViewportTest,
7840 TouchFlingCanLockToViewportLayerAfterBubbling) {
7841 gfx::Size content_size = gfx::Size(100, 160);
7842 gfx::Size outer_viewport = gfx::Size(50, 80);
7843 gfx::Size inner_viewport = gfx::Size(25, 40);
7845 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7847 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7848 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7850 scoped_ptr<LayerImpl> child =
7851 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7852 LayerImpl* child_scroll = child.get();
7853 outer_scroll->children()[0]->AddChild(child.Pass());
7855 DrawFrame();
7857 scoped_ptr<ScrollAndScaleSet> scroll_info;
7859 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7860 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7861 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7862 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7863 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7864 InputHandler::GESTURE));
7866 // The child should have scrolled up to its limit.
7867 scroll_info = host_impl_->ProcessScrollDeltas();
7868 ASSERT_EQ(1u, scroll_info->scrolls.size());
7869 EXPECT_TRUE(
7870 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7871 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7873 // The first |ScrollBy| after the fling should re-lock the scrolling
7874 // layer to the first layer that scrolled, the inner viewport scroll layer.
7875 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7876 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7877 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7878 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7879 InputHandler::GESTURE));
7881 // The inner viewport should have scrolled up to its limit.
7882 scroll_info = host_impl_->ProcessScrollDeltas();
7883 ASSERT_EQ(2u, scroll_info->scrolls.size());
7884 EXPECT_TRUE(
7885 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7886 EXPECT_TRUE(
7887 ScrollInfoContains(*scroll_info, inner_scroll->id(), scroll_delta));
7889 // As the locked layer is at its limit, no further scrolling can occur.
7890 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7891 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7892 host_impl_->ScrollEnd();
7893 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7894 gfx::Point(), InputHandler::GESTURE));
7898 TEST_F(LayerTreeHostImplVirtualViewportTest,
7899 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest) {
7900 gfx::Size content_size = gfx::Size(100, 160);
7901 gfx::Size outer_viewport = gfx::Size(50, 80);
7902 gfx::Size inner_viewport = gfx::Size(25, 40);
7904 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7906 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7907 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7909 scoped_ptr<LayerImpl> child =
7910 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7911 LayerImpl* child_scroll = child.get();
7912 outer_scroll->children()[0]->AddChild(child.Pass());
7914 DrawFrame();
7916 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7917 host_impl_->RootScrollBegin(InputHandler::GESTURE));
7918 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7919 host_impl_->ScrollEnd();
7920 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7921 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7922 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7923 host_impl_->ScrollEnd();
7926 TEST_F(LayerTreeHostImplVirtualViewportTest,
7927 NoOverscrollWhenInnerViewportCantScroll) {
7928 InputHandlerScrollResult scroll_result;
7929 gfx::Size content_size = gfx::Size(100, 160);
7930 gfx::Size outer_viewport = gfx::Size(50, 80);
7931 gfx::Size inner_viewport = gfx::Size(25, 40);
7932 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7933 DrawFrame();
7935 // Make inner viewport unscrollable.
7936 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7937 inner_scroll->set_user_scrollable_horizontal(false);
7938 inner_scroll->set_user_scrollable_vertical(false);
7940 // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
7941 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
7942 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7943 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7944 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
7945 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll->CurrentScrollOffset());
7947 // When inner viewport is unscrollable, a fling gives zero overscroll.
7948 EXPECT_FALSE(scroll_result.did_overscroll_root);
7949 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
7952 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7953 public:
7954 void SetUp() override {
7955 LayerTreeSettings settings = DefaultSettings();
7956 settings.max_memory_for_prepaint_percentage = 50;
7957 CreateHostImpl(settings, CreateOutputSurface());
7961 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7962 // Set up a memory policy and percentages which could cause
7963 // 32-bit integer overflows.
7964 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7966 // Verify implicit limits are calculated correctly with no overflows
7967 host_impl_->SetMemoryPolicy(mem_policy);
7968 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7969 300u * 1024u * 1024u);
7970 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7971 150u * 1024u * 1024u);
7974 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7975 const gfx::Size layer_size(100, 100);
7976 gfx::Transform external_transform;
7977 const gfx::Rect external_viewport(layer_size);
7978 const gfx::Rect external_clip(layer_size);
7979 const bool resourceless_software_draw = false;
7980 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7982 host_impl_->SetExternalDrawConstraints(external_transform,
7983 external_viewport,
7984 external_clip,
7985 external_viewport,
7986 external_transform,
7987 resourceless_software_draw);
7988 DrawFrame();
7989 EXPECT_TRANSFORMATION_MATRIX_EQ(
7990 external_transform, layer->draw_properties().target_space_transform);
7992 external_transform.Translate(20, 20);
7993 host_impl_->SetExternalDrawConstraints(external_transform,
7994 external_viewport,
7995 external_clip,
7996 external_viewport,
7997 external_transform,
7998 resourceless_software_draw);
7999 DrawFrame();
8000 EXPECT_TRANSFORMATION_MATRIX_EQ(
8001 external_transform, layer->draw_properties().target_space_transform);
8004 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
8005 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8006 DrawFrame();
8008 base::TimeTicks start_time =
8009 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8011 BeginFrameArgs begin_frame_args =
8012 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8014 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8015 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8017 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
8019 begin_frame_args.frame_time = start_time;
8020 host_impl_->WillBeginImplFrame(begin_frame_args);
8021 host_impl_->Animate();
8022 host_impl_->UpdateAnimationState(true);
8024 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
8025 host_impl_->DidFinishImplFrame();
8027 begin_frame_args.frame_time =
8028 start_time + base::TimeDelta::FromMilliseconds(50);
8029 host_impl_->WillBeginImplFrame(begin_frame_args);
8030 host_impl_->Animate();
8031 host_impl_->UpdateAnimationState(true);
8033 float y = scrolling_layer->CurrentScrollOffset().y();
8034 EXPECT_TRUE(y > 1 && y < 49);
8036 // Update target.
8037 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8038 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8039 host_impl_->DidFinishImplFrame();
8041 begin_frame_args.frame_time =
8042 start_time + base::TimeDelta::FromMilliseconds(200);
8043 host_impl_->WillBeginImplFrame(begin_frame_args);
8044 host_impl_->Animate();
8045 host_impl_->UpdateAnimationState(true);
8047 y = scrolling_layer->CurrentScrollOffset().y();
8048 EXPECT_TRUE(y > 50 && y < 100);
8049 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
8050 host_impl_->DidFinishImplFrame();
8052 begin_frame_args.frame_time =
8053 start_time + base::TimeDelta::FromMilliseconds(250);
8054 host_impl_->WillBeginImplFrame(begin_frame_args);
8055 host_impl_->Animate();
8056 host_impl_->UpdateAnimationState(true);
8058 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8059 scrolling_layer->CurrentScrollOffset());
8060 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
8061 host_impl_->DidFinishImplFrame();
8064 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
8065 TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
8066 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8067 DrawFrame();
8069 base::TimeTicks start_time =
8070 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8072 BeginFrameArgs begin_frame_args =
8073 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8075 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8076 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8078 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
8080 begin_frame_args.frame_time = start_time;
8081 host_impl_->WillBeginImplFrame(begin_frame_args);
8082 host_impl_->Animate();
8083 host_impl_->UpdateAnimationState(true);
8085 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
8086 host_impl_->DidFinishImplFrame();
8088 begin_frame_args.frame_time =
8089 start_time + base::TimeDelta::FromMilliseconds(50);
8090 host_impl_->WillBeginImplFrame(begin_frame_args);
8091 host_impl_->Animate();
8092 host_impl_->UpdateAnimationState(true);
8094 float y = scrolling_layer->CurrentScrollOffset().y();
8095 EXPECT_TRUE(y > 1 && y < 49);
8097 // Update target.
8098 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8099 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8100 host_impl_->DidFinishImplFrame();
8102 begin_frame_args.frame_time =
8103 start_time + base::TimeDelta::FromMilliseconds(200);
8104 host_impl_->WillBeginImplFrame(begin_frame_args);
8105 host_impl_->Animate();
8106 host_impl_->UpdateAnimationState(true);
8108 y = scrolling_layer->CurrentScrollOffset().y();
8109 EXPECT_TRUE(y > 50 && y < 100);
8110 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
8111 host_impl_->DidFinishImplFrame();
8113 begin_frame_args.frame_time =
8114 start_time + base::TimeDelta::FromMilliseconds(250);
8115 host_impl_->WillBeginImplFrame(begin_frame_args);
8116 host_impl_->Animate();
8117 host_impl_->UpdateAnimationState(true);
8119 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8120 scrolling_layer->CurrentScrollOffset());
8121 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
8122 host_impl_->DidFinishImplFrame();
8125 TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) {
8126 host_impl_->CreatePendingTree();
8128 Region empty_invalidation;
8129 scoped_refptr<RasterSource> pile_with_tiles(
8130 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
8131 gfx::Size(10, 10)));
8133 scoped_ptr<FakePictureLayerImpl> layer =
8134 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11);
8135 layer->SetBounds(gfx::Size(10, 10));
8136 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
8137 layer->SetDrawsContent(true);
8138 layer->tilings()->AddTiling(1.0f, pile_with_tiles);
8139 layer->UpdateRasterSource(pile_with_tiles, &empty_invalidation, nullptr);
8140 layer->tilings()->tiling_at(0)->set_resolution(
8141 TileResolution::HIGH_RESOLUTION);
8142 layer->tilings()->tiling_at(0)->CreateAllTilesForTesting();
8143 layer->tilings()->tiling_at(0)->ComputeTilePriorityRects(
8144 gfx::Rect(gfx::Size(10, 10)), 1.f, 1.0, Occlusion());
8145 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
8147 FakePictureLayerImpl* root_layer = static_cast<FakePictureLayerImpl*>(
8148 host_impl_->pending_tree()->root_layer());
8150 root_layer->set_has_valid_tile_priorities(true);
8151 scoped_ptr<RasterTilePriorityQueue> non_empty_raster_priority_queue_all =
8152 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
8153 RasterTilePriorityQueue::Type::ALL);
8154 EXPECT_FALSE(non_empty_raster_priority_queue_all->IsEmpty());
8156 root_layer->set_has_valid_tile_priorities(false);
8157 scoped_ptr<RasterTilePriorityQueue> empty_raster_priority_queue_all =
8158 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
8159 RasterTilePriorityQueue::Type::ALL);
8160 EXPECT_TRUE(empty_raster_priority_queue_all->IsEmpty());
8163 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
8164 host_impl_->CreatePendingTree();
8165 host_impl_->ActivateSyncTree();
8166 host_impl_->CreatePendingTree();
8168 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
8170 scoped_ptr<FakePictureLayerImpl> pending_layer =
8171 FakePictureLayerImpl::Create(pending_tree, 10);
8172 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
8173 pending_tree->SetRootLayer(pending_layer.Pass());
8174 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
8176 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
8177 pending_tree->DidBecomeActive();
8178 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
8180 scoped_ptr<FakePictureLayerImpl> mask_layer =
8181 FakePictureLayerImpl::Create(pending_tree, 11);
8182 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
8183 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
8184 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
8186 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
8187 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
8188 pending_tree->DidBecomeActive();
8189 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
8190 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
8192 scoped_ptr<FakePictureLayerImpl> replica_layer =
8193 FakePictureLayerImpl::Create(pending_tree, 12);
8194 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
8195 FakePictureLayerImpl::Create(pending_tree, 13);
8196 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
8197 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
8198 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
8199 ASSERT_EQ(raw_replica_mask_layer,
8200 raw_pending_layer->replica_layer()->mask_layer());
8202 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
8203 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
8204 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
8205 pending_tree->DidBecomeActive();
8206 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
8207 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
8208 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
8211 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
8212 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
8213 host_impl_->SetViewportSize(gfx::Size(50, 50));
8214 DrawFrame();
8216 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
8218 float min_page_scale = 1.f, max_page_scale = 4.f;
8219 float page_scale_factor = 1.f;
8221 // The scroll deltas should have the page scale factor applied.
8223 host_impl_->active_tree()->PushPageScaleFromMainThread(
8224 page_scale_factor, min_page_scale, max_page_scale);
8225 host_impl_->active_tree()->SetPageScaleOnActiveTree(page_scale_factor);
8226 scroll_layer->SetScrollDelta(gfx::Vector2d());
8228 float page_scale_delta = 2.f;
8229 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
8230 host_impl_->PinchGestureBegin();
8231 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
8232 host_impl_->PinchGestureEnd();
8233 host_impl_->ScrollEnd();
8235 gfx::Vector2dF scroll_delta(0, 5);
8236 EXPECT_EQ(InputHandler::SCROLL_STARTED,
8237 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
8238 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
8240 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
8241 host_impl_->ScrollEnd();
8242 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8243 scroll_layer->CurrentScrollOffset());
8247 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
8248 public:
8249 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8250 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
8252 protected:
8253 int num_lost_surfaces_;
8256 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
8257 // Really we just need at least one client notification each time
8258 // we go from having a valid output surface to not having a valid output
8259 // surface.
8260 EXPECT_EQ(0, num_lost_surfaces_);
8261 host_impl_->DidLoseOutputSurface();
8262 EXPECT_EQ(1, num_lost_surfaces_);
8263 host_impl_->DidLoseOutputSurface();
8264 EXPECT_LE(1, num_lost_surfaces_);
8267 TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) {
8268 LayerTreeHostImpl::FrameData frame;
8269 frame.render_passes.push_back(RenderPass::Create());
8270 RenderPass* pass3 = frame.render_passes.back();
8271 frame.render_passes.push_back(RenderPass::Create());
8272 RenderPass* pass2 = frame.render_passes.back();
8273 frame.render_passes.push_back(RenderPass::Create());
8274 RenderPass* pass1 = frame.render_passes.back();
8276 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8277 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8278 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8280 frame.render_passes_by_id[pass1->id] = pass1;
8281 frame.render_passes_by_id[pass2->id] = pass2;
8282 frame.render_passes_by_id[pass3->id] = pass3;
8284 // Add a quad to each pass so they aren't empty.
8285 SolidColorDrawQuad* color_quad;
8286 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8287 color_quad->material = DrawQuad::SOLID_COLOR;
8288 color_quad = pass2->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8289 color_quad->material = DrawQuad::SOLID_COLOR;
8290 color_quad = pass3->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8291 color_quad->material = DrawQuad::SOLID_COLOR;
8293 // pass3 is referenced by pass2.
8294 RenderPassDrawQuad* rpdq =
8295 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8296 rpdq->material = DrawQuad::RENDER_PASS;
8297 rpdq->render_pass_id = pass3->id;
8299 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
8300 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
8301 EXPECT_EQ(1u, frame.render_passes_by_id.size());
8302 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
8303 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
8304 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
8305 EXPECT_EQ(1u, frame.render_passes.size());
8306 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
8309 TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) {
8310 LayerTreeHostImpl::FrameData frame;
8311 frame.render_passes.push_back(RenderPass::Create());
8312 RenderPass* pass3 = frame.render_passes.back();
8313 frame.render_passes.push_back(RenderPass::Create());
8314 RenderPass* pass2 = frame.render_passes.back();
8315 frame.render_passes.push_back(RenderPass::Create());
8316 RenderPass* pass1 = frame.render_passes.back();
8318 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8319 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8320 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8322 frame.render_passes_by_id[pass1->id] = pass1;
8323 frame.render_passes_by_id[pass2->id] = pass2;
8324 frame.render_passes_by_id[pass3->id] = pass3;
8326 // pass1 is not empty, but pass2 and pass3 are.
8327 SolidColorDrawQuad* color_quad;
8328 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
8329 color_quad->material = DrawQuad::SOLID_COLOR;
8331 // pass3 is referenced by pass2.
8332 RenderPassDrawQuad* rpdq =
8333 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8334 rpdq->material = DrawQuad::RENDER_PASS;
8335 rpdq->render_pass_id = pass3->id;
8337 // pass2 is referenced by pass1.
8338 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8339 rpdq->material = DrawQuad::RENDER_PASS;
8340 rpdq->render_pass_id = pass2->id;
8342 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8343 // should be removed.
8344 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
8345 EXPECT_EQ(1u, frame.render_passes_by_id.size());
8346 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
8347 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
8348 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
8349 EXPECT_EQ(1u, frame.render_passes.size());
8350 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
8351 // The RenderPassDrawQuad should be removed from pass1.
8352 EXPECT_EQ(1u, pass1->quad_list.size());
8353 EXPECT_EQ(DrawQuad::SOLID_COLOR, pass1->quad_list.ElementAt(0)->material);
8356 TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) {
8357 LayerTreeHostImpl::FrameData frame;
8358 frame.render_passes.push_back(RenderPass::Create());
8359 RenderPass* pass3 = frame.render_passes.back();
8360 frame.render_passes.push_back(RenderPass::Create());
8361 RenderPass* pass2 = frame.render_passes.back();
8362 frame.render_passes.push_back(RenderPass::Create());
8363 RenderPass* pass1 = frame.render_passes.back();
8365 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8366 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8367 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8369 frame.render_passes_by_id[pass1->id] = pass1;
8370 frame.render_passes_by_id[pass2->id] = pass2;
8371 frame.render_passes_by_id[pass3->id] = pass3;
8373 // pass3 is referenced by pass2.
8374 RenderPassDrawQuad* rpdq =
8375 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8376 rpdq->material = DrawQuad::RENDER_PASS;
8377 rpdq->render_pass_id = pass3->id;
8379 // pass2 is referenced by pass1.
8380 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8381 rpdq->material = DrawQuad::RENDER_PASS;
8382 rpdq->render_pass_id = pass2->id;
8384 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8385 // should be removed. Then pass1 is empty too, but it's the root so it should
8386 // not be removed.
8387 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
8388 EXPECT_EQ(1u, frame.render_passes_by_id.size());
8389 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
8390 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
8391 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
8392 EXPECT_EQ(1u, frame.render_passes.size());
8393 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
8394 // The RenderPassDrawQuad should be removed from pass1.
8395 EXPECT_EQ(0u, pass1->quad_list.size());
8398 class FakeVideoFrameController : public VideoFrameController {
8399 public:
8400 void OnBeginFrame(const BeginFrameArgs& args) override {
8401 begin_frame_args_ = args;
8402 did_draw_frame_ = false;
8405 void DidDrawFrame() override { did_draw_frame_ = true; }
8407 const BeginFrameArgs& begin_frame_args() const { return begin_frame_args_; }
8409 bool did_draw_frame() const { return did_draw_frame_; }
8411 private:
8412 BeginFrameArgs begin_frame_args_;
8413 bool did_draw_frame_ = false;
8416 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
8417 BeginFrameArgs begin_frame_args =
8418 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8419 FakeVideoFrameController controller;
8421 host_impl_->WillBeginImplFrame(begin_frame_args);
8422 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8423 host_impl_->AddVideoFrameController(&controller);
8424 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8425 host_impl_->DidFinishImplFrame();
8427 EXPECT_FALSE(controller.did_draw_frame());
8428 LayerTreeHostImpl::FrameData frame;
8429 host_impl_->DidDrawAllLayers(frame);
8430 EXPECT_TRUE(controller.did_draw_frame());
8432 controller.OnBeginFrame(begin_frame_args);
8433 EXPECT_FALSE(controller.did_draw_frame());
8434 host_impl_->RemoveVideoFrameController(&controller);
8435 host_impl_->DidDrawAllLayers(frame);
8436 EXPECT_FALSE(controller.did_draw_frame());
8439 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) {
8440 BeginFrameArgs begin_frame_args =
8441 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8442 FakeVideoFrameController controller;
8444 host_impl_->WillBeginImplFrame(begin_frame_args);
8445 host_impl_->DidFinishImplFrame();
8447 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8448 host_impl_->AddVideoFrameController(&controller);
8449 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8451 begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8452 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8453 host_impl_->WillBeginImplFrame(begin_frame_args);
8454 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8456 EXPECT_FALSE(controller.did_draw_frame());
8457 LayerTreeHostImpl::FrameData frame;
8458 host_impl_->DidDrawAllLayers(frame);
8459 EXPECT_TRUE(controller.did_draw_frame());
8461 controller.OnBeginFrame(begin_frame_args);
8462 EXPECT_FALSE(controller.did_draw_frame());
8463 host_impl_->RemoveVideoFrameController(&controller);
8464 host_impl_->DidDrawAllLayers(frame);
8465 EXPECT_FALSE(controller.did_draw_frame());
8468 TEST_F(LayerTreeHostImplTest, GpuRasterizationStatusModes) {
8469 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8471 host_impl_->SetHasGpuRasterizationTrigger(true);
8472 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8473 EXPECT_EQ(GpuRasterizationStatus::ON, host_impl_->gpu_rasterization_status());
8474 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8476 host_impl_->SetHasGpuRasterizationTrigger(false);
8477 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8478 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT,
8479 host_impl_->gpu_rasterization_status());
8480 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8482 host_impl_->SetHasGpuRasterizationTrigger(true);
8483 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8484 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT,
8485 host_impl_->gpu_rasterization_status());
8486 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8487 EXPECT_FALSE(host_impl_->use_msaa());
8489 scoped_ptr<TestWebGraphicsContext3D> context_with_msaa =
8490 TestWebGraphicsContext3D::Create();
8491 context_with_msaa->SetMaxSamples(8);
8493 LayerTreeSettings msaaSettings = GpuRasterizationEnabledSettings();
8494 msaaSettings.gpu_rasterization_msaa_sample_count = 4;
8495 EXPECT_TRUE(CreateHostImpl(
8496 msaaSettings, FakeOutputSurface::Create3d(context_with_msaa.Pass())));
8497 host_impl_->SetHasGpuRasterizationTrigger(true);
8498 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8499 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT,
8500 host_impl_->gpu_rasterization_status());
8501 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8502 EXPECT_TRUE(host_impl_->use_msaa());
8504 LayerTreeSettings settings = DefaultSettings();
8505 settings.gpu_rasterization_enabled = false;
8506 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8507 host_impl_->SetHasGpuRasterizationTrigger(true);
8508 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8509 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE,
8510 host_impl_->gpu_rasterization_status());
8511 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8513 settings.gpu_rasterization_forced = true;
8514 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8516 host_impl_->SetHasGpuRasterizationTrigger(false);
8517 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8518 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED,
8519 host_impl_->gpu_rasterization_status());
8520 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8523 // A mock output surface which lets us detect calls to ForceReclaimResources.
8524 class MockReclaimResourcesOutputSurface : public FakeOutputSurface {
8525 public:
8526 static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() {
8527 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8528 TestContextProvider::Create(), TestContextProvider::Create(), false));
8531 MOCK_METHOD0(ForceReclaimResources, void());
8533 protected:
8534 MockReclaimResourcesOutputSurface(
8535 scoped_refptr<ContextProvider> context_provider,
8536 scoped_refptr<ContextProvider> worker_context_provider,
8537 bool delegated_rendering)
8538 : FakeOutputSurface(context_provider,
8539 worker_context_provider,
8540 delegated_rendering) {}
8543 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8544 // being reclaimed to block drawing between BeginCommit / Swap. This test
8545 // ensures that BeginCommit triggers ForceReclaimResources. See
8546 // crbug.com/489515.
8547 TEST_F(LayerTreeHostImplTest, BeginCommitReclaimsResources) {
8548 scoped_ptr<MockReclaimResourcesOutputSurface> output_surface(
8549 MockReclaimResourcesOutputSurface::Create3d());
8550 // Hold an unowned pointer to the output surface to use for mock expectations.
8551 MockReclaimResourcesOutputSurface* mock_output_surface = output_surface.get();
8553 CreateHostImpl(DefaultSettings(), output_surface.Pass());
8554 EXPECT_CALL(*mock_output_surface, ForceReclaimResources()).Times(1);
8555 host_impl_->BeginCommit();
8558 } // namespace
8559 } // namespace cc