Roll src/third_party/skia 99c7c07:4af6580
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob073d5ae1a08814c6621a8e232da88117f927d3a4
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/base/math_util.h"
18 #include "cc/input/page_scale_animation.h"
19 #include "cc/input/top_controls_manager.h"
20 #include "cc/layers/append_quads_data.h"
21 #include "cc/layers/delegated_renderer_layer_impl.h"
22 #include "cc/layers/heads_up_display_layer_impl.h"
23 #include "cc/layers/io_surface_layer_impl.h"
24 #include "cc/layers/layer_impl.h"
25 #include "cc/layers/painted_scrollbar_layer_impl.h"
26 #include "cc/layers/render_surface_impl.h"
27 #include "cc/layers/solid_color_layer_impl.h"
28 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
29 #include "cc/layers/texture_layer_impl.h"
30 #include "cc/layers/tiled_layer_impl.h"
31 #include "cc/layers/video_layer_impl.h"
32 #include "cc/output/begin_frame_args.h"
33 #include "cc/output/compositor_frame_ack.h"
34 #include "cc/output/compositor_frame_metadata.h"
35 #include "cc/output/copy_output_request.h"
36 #include "cc/output/copy_output_result.h"
37 #include "cc/output/gl_renderer.h"
38 #include "cc/output/latency_info_swap_promise.h"
39 #include "cc/quads/render_pass_draw_quad.h"
40 #include "cc/quads/solid_color_draw_quad.h"
41 #include "cc/quads/texture_draw_quad.h"
42 #include "cc/quads/tile_draw_quad.h"
43 #include "cc/resources/layer_tiling_data.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/layer_test_common.h"
55 #include "cc/test/layer_tree_test.h"
56 #include "cc/test/render_pass_test_common.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/frame_time.h"
68 #include "ui/gfx/geometry/rect_conversions.h"
69 #include "ui/gfx/geometry/size_conversions.h"
70 #include "ui/gfx/geometry/vector2d_conversions.h"
72 using ::testing::Mock;
73 using ::testing::Return;
74 using ::testing::AnyNumber;
75 using ::testing::AtLeast;
76 using ::testing::_;
77 using media::VideoFrame;
79 namespace cc {
80 namespace {
82 class LayerTreeHostImplTest : public testing::Test,
83 public LayerTreeHostImplClient {
84 public:
85 LayerTreeHostImplTest()
86 : proxy_(base::ThreadTaskRunnerHandle::Get(),
87 base::ThreadTaskRunnerHandle::Get()),
88 always_impl_thread_(&proxy_),
89 always_main_thread_blocked_(&proxy_),
90 shared_bitmap_manager_(new TestSharedBitmapManager),
91 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager),
92 task_graph_runner_(new TestTaskGraphRunner),
93 on_can_draw_state_changed_called_(false),
94 did_notify_ready_to_activate_(false),
95 did_request_commit_(false),
96 did_request_redraw_(false),
97 did_request_animate_(false),
98 did_request_prepare_tiles_(false),
99 did_complete_page_scale_animation_(false),
100 reduce_memory_result_(true),
101 current_limit_bytes_(0),
102 current_priority_cutoff_value_(0) {
103 media::InitializeMediaLibraryForTesting();
106 LayerTreeSettings DefaultSettings() {
107 LayerTreeSettings settings;
108 settings.minimum_occlusion_tracking_size = gfx::Size();
109 settings.impl_side_painting = true;
110 settings.renderer_settings.texture_id_allocation_chunk_size = 1;
111 settings.report_overscroll_only_for_scrollable_axes = true;
112 settings.use_pinch_virtual_viewport = true;
113 return settings;
116 void SetUp() override {
117 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
120 void TearDown() override {}
122 void UpdateRendererCapabilitiesOnImplThread() override {}
123 void DidLoseOutputSurfaceOnImplThread() override {}
124 void CommitVSyncParameters(base::TimeTicks timebase,
125 base::TimeDelta interval) override {}
126 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
127 void SetMaxSwapsPendingOnImplThread(int max) override {}
128 void DidSwapBuffersOnImplThread() override {}
129 void DidSwapBuffersCompleteOnImplThread() override {}
130 void OnCanDrawStateChanged(bool can_draw) override {
131 on_can_draw_state_changed_called_ = true;
133 void NotifyReadyToActivate() override {
134 did_notify_ready_to_activate_ = true;
135 host_impl_->ActivateSyncTree();
137 void NotifyReadyToDraw() override {}
138 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
139 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
140 did_request_redraw_ = true;
142 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
143 void SetNeedsPrepareTilesOnImplThread() override {
144 did_request_prepare_tiles_ = true;
146 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
147 void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
148 void PostAnimationEventsToMainThreadOnImplThread(
149 scoped_ptr<AnimationEventsVector> events) override {}
150 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes,
151 int priority_cutoff) override {
152 current_limit_bytes_ = limit_bytes;
153 current_priority_cutoff_value_ = priority_cutoff;
154 return reduce_memory_result_;
156 bool IsInsideDraw() override { return false; }
157 void RenewTreePriority() override {}
158 void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
159 base::TimeDelta delay) override {
160 animation_task_ = task;
161 requested_animation_delay_ = delay;
163 void DidActivateSyncTree() override {}
164 void DidPrepareTiles() override {}
165 void DidCompletePageScaleAnimationOnImplThread() override {
166 did_complete_page_scale_animation_ = true;
168 void OnDrawForOutputSurface() override {}
170 void set_reduce_memory_result(bool reduce_memory_result) {
171 reduce_memory_result_ = reduce_memory_result;
174 virtual bool CreateHostImpl(const LayerTreeSettings& settings,
175 scoped_ptr<OutputSurface> output_surface) {
176 host_impl_ = LayerTreeHostImpl::Create(
177 settings, this, &proxy_, &stats_instrumentation_,
178 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
179 task_graph_runner_.get(), 0);
180 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
181 host_impl_->SetViewportSize(gfx::Size(10, 10));
182 return init;
185 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
186 root->SetPosition(gfx::PointF());
187 root->SetBounds(gfx::Size(10, 10));
188 root->SetContentBounds(gfx::Size(10, 10));
189 root->SetDrawsContent(true);
190 root->draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
191 root->SetHasRenderSurface(true);
192 host_impl_->active_tree()->SetRootLayer(root.Pass());
195 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
196 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
197 for (size_t i = 0; i < layer->children().size(); ++i)
198 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
201 static void ExpectContains(const ScrollAndScaleSet& scroll_info,
202 int id,
203 const gfx::Vector2d& scroll_delta) {
204 int times_encountered = 0;
206 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
207 if (scroll_info.scrolls[i].layer_id != id)
208 continue;
209 EXPECT_VECTOR_EQ(scroll_delta, scroll_info.scrolls[i].scroll_delta);
210 times_encountered++;
213 ASSERT_EQ(1, times_encountered);
216 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
217 int times_encountered = 0;
219 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
220 if (scroll_info.scrolls[i].layer_id != id)
221 continue;
222 times_encountered++;
225 ASSERT_EQ(0, times_encountered);
228 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
229 const gfx::Size& content_size) {
230 // Create both an inner viewport scroll layer and an outer viewport scroll
231 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
232 // 0x0, so the scrolls will be applied directly to the inner viewport.
233 const int kOuterViewportClipLayerId = 116;
234 const int kOuterViewportScrollLayerId = 117;
235 const int kContentLayerId = 118;
236 const int kInnerViewportScrollLayerId = 2;
237 const int kInnerViewportClipLayerId = 4;
238 const int kPageScaleLayerId = 5;
240 scoped_ptr<LayerImpl> root =
241 LayerImpl::Create(layer_tree_impl, 1);
242 root->SetBounds(content_size);
243 root->SetContentBounds(content_size);
244 root->SetPosition(gfx::PointF());
245 root->SetHasRenderSurface(true);
247 scoped_ptr<LayerImpl> inner_scroll =
248 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
249 inner_scroll->SetIsContainerForFixedPositionLayers(true);
250 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
252 scoped_ptr<LayerImpl> inner_clip =
253 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
254 inner_clip->SetBounds(
255 gfx::Size(content_size.width() / 2, content_size.height() / 2));
257 scoped_ptr<LayerImpl> page_scale =
258 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
260 inner_scroll->SetScrollClipLayer(inner_clip->id());
261 inner_scroll->SetBounds(content_size);
262 inner_scroll->SetContentBounds(content_size);
263 inner_scroll->SetPosition(gfx::PointF());
265 scoped_ptr<LayerImpl> outer_clip =
266 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
267 outer_clip->SetBounds(content_size);
268 outer_clip->SetIsContainerForFixedPositionLayers(true);
270 scoped_ptr<LayerImpl> outer_scroll =
271 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
272 outer_scroll->SetScrollClipLayer(outer_clip->id());
273 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
274 outer_scroll->SetBounds(content_size);
275 outer_scroll->SetContentBounds(content_size);
276 outer_scroll->SetPosition(gfx::PointF());
278 scoped_ptr<LayerImpl> contents =
279 LayerImpl::Create(layer_tree_impl, kContentLayerId);
280 contents->SetDrawsContent(true);
281 contents->SetBounds(content_size);
282 contents->SetContentBounds(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 // TODO(wjmaclean) Add clip-layer pointer to parameters.
309 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
310 const gfx::Size& size,
311 LayerImpl* clip_layer) {
312 DCHECK(clip_layer);
313 DCHECK(id != clip_layer->id());
314 scoped_ptr<LayerImpl> layer =
315 LayerImpl::Create(host_impl_->active_tree(), id);
316 layer->SetScrollClipLayer(clip_layer->id());
317 layer->SetDrawsContent(true);
318 layer->SetBounds(size);
319 layer->SetContentBounds(size);
320 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
321 return layer.Pass();
324 void DrawFrame() {
325 LayerTreeHostImpl::FrameData frame;
326 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
327 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
328 host_impl_->DidDrawAllLayers(frame);
331 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
332 void pinch_zoom_pan_viewport_test(float device_scale_factor);
333 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
334 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
335 float device_scale_factor);
337 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
338 // Note: It is not possible to disable the renderer once it has been set,
339 // so we do not need to test that disabling the renderer notifies us
340 // that can_draw changed.
341 EXPECT_FALSE(host_impl_->CanDraw());
342 on_can_draw_state_changed_called_ = false;
344 // Set up the root layer, which allows us to draw.
345 SetupScrollAndContentsLayers(gfx::Size(100, 100));
346 EXPECT_TRUE(host_impl_->CanDraw());
347 EXPECT_TRUE(on_can_draw_state_changed_called_);
348 on_can_draw_state_changed_called_ = false;
350 // Toggle the root layer to make sure it toggles can_draw
351 host_impl_->active_tree()->SetRootLayer(nullptr);
352 EXPECT_FALSE(host_impl_->CanDraw());
353 EXPECT_TRUE(on_can_draw_state_changed_called_);
354 on_can_draw_state_changed_called_ = false;
356 SetupScrollAndContentsLayers(gfx::Size(100, 100));
357 EXPECT_TRUE(host_impl_->CanDraw());
358 EXPECT_TRUE(on_can_draw_state_changed_called_);
359 on_can_draw_state_changed_called_ = false;
361 // Toggle the device viewport size to make sure it toggles can_draw.
362 host_impl_->SetViewportSize(gfx::Size());
363 if (always_draw) {
364 EXPECT_TRUE(host_impl_->CanDraw());
365 } else {
366 EXPECT_FALSE(host_impl_->CanDraw());
368 EXPECT_TRUE(on_can_draw_state_changed_called_);
369 on_can_draw_state_changed_called_ = false;
371 host_impl_->SetViewportSize(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 contents textures purged without causing any evictions,
377 // and make sure that it does not change can_draw.
378 set_reduce_memory_result(false);
379 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
380 host_impl_->memory_allocation_limit_bytes() - 1));
381 EXPECT_TRUE(host_impl_->CanDraw());
382 EXPECT_FALSE(on_can_draw_state_changed_called_);
383 on_can_draw_state_changed_called_ = false;
385 // Toggle contents textures purged to make sure it toggles can_draw.
386 set_reduce_memory_result(true);
387 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
388 host_impl_->memory_allocation_limit_bytes() - 1));
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_->active_tree()->ResetContentsTexturesPurged();
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 scoped_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
421 scoped_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
422 scoped_ptr<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_;
435 size_t current_limit_bytes_;
436 int current_priority_cutoff_value_;
439 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
440 bool always_draw = false;
441 CheckNotifyCalledIfCanDrawChanged(always_draw);
444 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
445 CreateHostImpl(DefaultSettings(),
446 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
448 bool always_draw = true;
449 CheckNotifyCalledIfCanDrawChanged(always_draw);
452 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
453 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
455 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
456 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
459 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
461 scoped_ptr<LayerImpl> root =
462 LayerImpl::Create(host_impl_->active_tree(), 1);
463 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
464 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
465 root->children()[1]->AddChild(
466 LayerImpl::Create(host_impl_->active_tree(), 4));
467 root->children()[1]->AddChild(
468 LayerImpl::Create(host_impl_->active_tree(), 5));
469 root->children()[1]->children()[0]->AddChild(
470 LayerImpl::Create(host_impl_->active_tree(), 6));
471 host_impl_->active_tree()->SetRootLayer(root.Pass());
473 LayerImpl* root = host_impl_->active_tree()->root_layer();
475 ExpectClearedScrollDeltasRecursive(root);
477 scoped_ptr<ScrollAndScaleSet> scroll_info;
479 scroll_info = host_impl_->ProcessScrollDeltas();
480 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
481 ExpectClearedScrollDeltasRecursive(root);
483 scroll_info = host_impl_->ProcessScrollDeltas();
484 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
485 ExpectClearedScrollDeltasRecursive(root);
488 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
489 gfx::ScrollOffset scroll_offset(20, 30);
490 gfx::Vector2d scroll_delta(11, -15);
492 scoped_ptr<LayerImpl> root_clip =
493 LayerImpl::Create(host_impl_->active_tree(), 2);
494 scoped_ptr<LayerImpl> root =
495 LayerImpl::Create(host_impl_->active_tree(), 1);
496 root_clip->SetBounds(gfx::Size(10, 10));
497 LayerImpl* root_layer = root.get();
498 root_clip->AddChild(root.Pass());
499 root_layer->SetBounds(gfx::Size(110, 110));
500 root_layer->SetScrollClipLayer(root_clip->id());
501 root_layer->PushScrollOffsetFromMainThread(scroll_offset);
502 root_layer->ScrollBy(scroll_delta);
503 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
505 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
507 scoped_ptr<ScrollAndScaleSet> scroll_info;
509 scroll_info = host_impl_->ProcessScrollDeltas();
510 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
511 ExpectContains(*scroll_info, root->id(), scroll_delta);
513 gfx::Vector2d scroll_delta2(-5, 27);
514 root->ScrollBy(scroll_delta2);
515 scroll_info = host_impl_->ProcessScrollDeltas();
516 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
517 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
519 root->ScrollBy(gfx::Vector2d());
520 scroll_info = host_impl_->ProcessScrollDeltas();
521 ExpectContains(*scroll_info, root->id(), scroll_delta + scroll_delta2);
524 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
525 SetupScrollAndContentsLayers(gfx::Size(100, 100));
526 host_impl_->SetViewportSize(gfx::Size(50, 50));
527 DrawFrame();
529 EXPECT_EQ(InputHandler::SCROLL_STARTED,
530 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
531 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
532 InputHandler::WHEEL));
533 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
534 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
535 InputHandler::WHEEL));
536 host_impl_->ScrollEnd();
537 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
538 InputHandler::WHEEL));
539 EXPECT_TRUE(did_request_redraw_);
540 EXPECT_TRUE(did_request_commit_);
543 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
544 SetupScrollAndContentsLayers(gfx::Size(100, 100));
545 host_impl_->SetViewportSize(gfx::Size(50, 50));
546 DrawFrame();
548 EXPECT_EQ(InputHandler::SCROLL_STARTED,
549 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
550 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
551 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
552 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
553 host_impl_->ScrollEnd();
554 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
557 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
558 // We should not crash when trying to scroll an empty layer tree.
559 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
560 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
563 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
564 scoped_ptr<TestWebGraphicsContext3D> context_owned =
565 TestWebGraphicsContext3D::Create();
566 context_owned->set_context_lost(true);
568 // Initialization will fail.
569 EXPECT_FALSE(CreateHostImpl(
570 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
572 SetupScrollAndContentsLayers(gfx::Size(100, 100));
574 // We should not crash when trying to scroll after the renderer initialization
575 // fails.
576 EXPECT_EQ(InputHandler::SCROLL_STARTED,
577 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
580 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
581 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
582 host_impl_->SetViewportSize(gfx::Size(50, 50));
583 DrawFrame();
585 // We should not crash if the tree is replaced while we are scrolling.
586 EXPECT_EQ(InputHandler::SCROLL_STARTED,
587 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
588 host_impl_->active_tree()->DetachLayerTree();
590 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
592 // We should still be scrolling, because the scrolled layer also exists in the
593 // new tree.
594 gfx::Vector2d scroll_delta(0, 10);
595 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
596 host_impl_->ScrollEnd();
597 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
598 ExpectContains(*scroll_info, scroll_layer->id(), scroll_delta);
601 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
602 SetupScrollAndContentsLayers(gfx::Size(100, 100));
603 host_impl_->SetViewportSize(gfx::Size(50, 50));
604 DrawFrame();
605 LayerImpl* root = host_impl_->active_tree()->root_layer();
607 // With registered event handlers, wheel scrolls don't necessarily
608 // have to go to the main thread.
609 root->SetHaveWheelEventHandlers(true);
610 EXPECT_EQ(InputHandler::SCROLL_STARTED,
611 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
612 host_impl_->ScrollEnd();
614 // But typically the scroll-blocks-on mode will require them to.
615 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
616 SCROLL_BLOCKS_ON_START_TOUCH);
617 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
618 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
620 // But gesture scrolls can still be handled.
621 EXPECT_EQ(InputHandler::SCROLL_STARTED,
622 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
623 host_impl_->ScrollEnd();
625 // And if the handlers go away, wheel scrolls can again be processed
626 // on impl (despite the scroll-blocks-on mode).
627 root->SetHaveWheelEventHandlers(false);
628 EXPECT_EQ(InputHandler::SCROLL_STARTED,
629 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
630 host_impl_->ScrollEnd();
633 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
634 LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
635 host_impl_->SetViewportSize(gfx::Size(50, 50));
636 DrawFrame();
637 LayerImpl* root = host_impl_->active_tree()->root_layer();
639 LayerImpl* child = 0;
641 scoped_ptr<LayerImpl> child_layer =
642 LayerImpl::Create(host_impl_->active_tree(), 6);
643 child = child_layer.get();
644 child_layer->SetDrawsContent(true);
645 child_layer->SetPosition(gfx::PointF(0, 20));
646 child_layer->SetBounds(gfx::Size(50, 50));
647 child_layer->SetContentBounds(gfx::Size(50, 50));
648 scroll->AddChild(child_layer.Pass());
651 // Touch handler regions determine whether touch events block scroll.
652 root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
653 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
654 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH |
655 SCROLL_BLOCKS_ON_WHEEL_EVENT);
656 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
658 // But they don't influence the actual handling of the scroll gestures.
659 EXPECT_EQ(InputHandler::SCROLL_STARTED,
660 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
661 host_impl_->ScrollEnd();
663 // It's the union of scroll-blocks-on mode bits across all layers in the
664 // scroll paret chain that matters.
665 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
666 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE);
667 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
668 child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH);
669 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
672 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
673 SetupScrollAndContentsLayers(gfx::Size(100, 100));
674 host_impl_->SetViewportSize(gfx::Size(50, 50));
675 DrawFrame();
676 LayerImpl* root = host_impl_->active_tree()->root_layer();
678 // With registered scroll handlers, scrolls don't generally have to go
679 // to the main thread.
680 root->SetHaveScrollEventHandlers(true);
681 EXPECT_EQ(InputHandler::SCROLL_STARTED,
682 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
683 host_impl_->ScrollEnd();
685 // Even the default scroll blocks on mode doesn't require this.
686 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
687 SCROLL_BLOCKS_ON_START_TOUCH);
688 EXPECT_EQ(InputHandler::SCROLL_STARTED,
689 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
690 host_impl_->ScrollEnd();
692 // But the page can opt in to blocking on scroll event handlers.
693 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
694 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
695 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
697 // GESTURE and WHEEL scrolls behave identically in this regard.
698 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
699 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
701 // And if the handlers go away, scrolls can again be processed on impl
702 // (despite the scroll-blocks-on mode).
703 root->SetHaveScrollEventHandlers(false);
704 EXPECT_EQ(InputHandler::SCROLL_STARTED,
705 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
706 host_impl_->ScrollEnd();
709 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
710 host_impl_->SetViewportSize(gfx::Size(50, 50));
712 // Create a normal scrollable root layer
713 LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
714 LayerImpl* root_child = root_scroll->children()[0];
715 LayerImpl* root = host_impl_->active_tree()->root_layer();
716 DrawFrame();
718 // Create two child scrollable layers
719 LayerImpl* child1 = 0;
721 scoped_ptr<LayerImpl> scrollable_child_clip_1 =
722 LayerImpl::Create(host_impl_->active_tree(), 6);
723 scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
724 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
725 child1 = scrollable_child_1.get();
726 scrollable_child_1->SetPosition(gfx::Point(5, 5));
727 scrollable_child_1->SetHaveWheelEventHandlers(true);
728 scrollable_child_1->SetHaveScrollEventHandlers(true);
729 scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
730 root_child->AddChild(scrollable_child_clip_1.Pass());
733 LayerImpl* child2 = 0;
735 scoped_ptr<LayerImpl> scrollable_child_clip_2 =
736 LayerImpl::Create(host_impl_->active_tree(), 8);
737 scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
738 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
739 child2 = scrollable_child_2.get();
740 scrollable_child_2->SetPosition(gfx::Point(5, 20));
741 scrollable_child_2->SetHaveWheelEventHandlers(true);
742 scrollable_child_2->SetHaveScrollEventHandlers(true);
743 scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
744 root_child->AddChild(scrollable_child_clip_2.Pass());
747 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
748 EXPECT_EQ(InputHandler::SCROLL_STARTED,
749 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
750 host_impl_->ScrollEnd();
751 child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
752 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
753 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
755 // But not those that hit only other layers.
756 EXPECT_EQ(InputHandler::SCROLL_STARTED,
757 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
758 host_impl_->ScrollEnd();
760 // It's the union of bits set across the scroll ancestor chain that matters.
761 EXPECT_EQ(InputHandler::SCROLL_STARTED,
762 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
763 host_impl_->ScrollEnd();
764 EXPECT_EQ(InputHandler::SCROLL_STARTED,
765 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
766 host_impl_->ScrollEnd();
767 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT);
768 EXPECT_EQ(InputHandler::SCROLL_STARTED,
769 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
770 host_impl_->ScrollEnd();
771 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
772 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
773 child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
774 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
775 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
776 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
777 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
780 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
781 SetupScrollAndContentsLayers(gfx::Size(100, 100));
782 host_impl_->SetViewportSize(gfx::Size(50, 50));
783 DrawFrame();
785 // Ignore the fling since no layer is being scrolled
786 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
788 // Start scrolling a layer
789 EXPECT_EQ(InputHandler::SCROLL_STARTED,
790 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
792 // Now the fling should go ahead since we've started scrolling a layer
793 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
796 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
797 SetupScrollAndContentsLayers(gfx::Size(100, 100));
798 host_impl_->SetViewportSize(gfx::Size(50, 50));
799 DrawFrame();
801 // Ignore the fling since no layer is being scrolled
802 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
804 // Start scrolling a layer
805 EXPECT_EQ(InputHandler::SCROLL_STARTED,
806 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
808 // Now the fling should go ahead since we've started scrolling a layer
809 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
812 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
813 SetupScrollAndContentsLayers(gfx::Size(100, 100));
814 host_impl_->SetViewportSize(gfx::Size(50, 50));
815 DrawFrame();
816 LayerImpl* root = host_impl_->active_tree()->root_layer();
818 root->SetShouldScrollOnMainThread(true);
820 // Start scrolling a layer
821 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
822 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
824 // The fling should be ignored since there's no layer being scrolled impl-side
825 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
828 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
829 SetupScrollAndContentsLayers(gfx::Size(100, 100));
830 host_impl_->SetViewportSize(gfx::Size(50, 50));
831 DrawFrame();
832 LayerImpl* root = host_impl_->active_tree()->root_layer();
834 root->SetShouldScrollOnMainThread(true);
836 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
837 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
838 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
839 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
842 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
843 SetupScrollAndContentsLayers(gfx::Size(200, 200));
844 host_impl_->SetViewportSize(gfx::Size(100, 100));
846 LayerImpl* root = host_impl_->active_tree()->root_layer();
847 root->SetContentsScale(2.f, 2.f);
848 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
850 DrawFrame();
852 // All scroll types inside the non-fast scrollable region should fail.
853 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
854 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL));
855 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
856 InputHandler::WHEEL));
857 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
858 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE));
859 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
860 InputHandler::GESTURE));
862 // All scroll types outside this region should succeed.
863 EXPECT_EQ(InputHandler::SCROLL_STARTED,
864 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL));
865 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
866 InputHandler::GESTURE));
867 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
868 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
869 InputHandler::GESTURE));
870 host_impl_->ScrollEnd();
871 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
872 InputHandler::GESTURE));
873 EXPECT_EQ(InputHandler::SCROLL_STARTED,
874 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE));
875 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
876 InputHandler::GESTURE));
877 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
878 host_impl_->ScrollEnd();
879 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
880 InputHandler::GESTURE));
883 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
884 SetupScrollAndContentsLayers(gfx::Size(200, 200));
885 host_impl_->SetViewportSize(gfx::Size(100, 100));
887 LayerImpl* root = host_impl_->active_tree()->root_layer();
888 root->SetContentsScale(2.f, 2.f);
889 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
890 root->SetPosition(gfx::PointF(-25.f, 0.f));
892 DrawFrame();
894 // This point would fall into the non-fast scrollable region except that we've
895 // moved the layer down by 25 pixels.
896 EXPECT_EQ(InputHandler::SCROLL_STARTED,
897 host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL));
898 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
899 InputHandler::WHEEL));
900 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
901 host_impl_->ScrollEnd();
903 // This point is still inside the non-fast region.
904 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
905 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL));
908 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
909 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
910 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
911 host_impl_->SetViewportSize(gfx::Size(50, 50));
912 DrawFrame();
914 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
915 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
916 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
917 host_impl_->ScrollEnd();
918 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
921 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
922 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
923 scroll_layer->SetHaveScrollEventHandlers(true);
924 host_impl_->SetViewportSize(gfx::Size(50, 50));
925 DrawFrame();
927 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
928 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
929 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
930 host_impl_->ScrollEnd();
931 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
934 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
935 SetupScrollAndContentsLayers(gfx::Size(200, 200));
936 host_impl_->SetViewportSize(gfx::Size(100, 100));
938 DrawFrame();
940 EXPECT_EQ(InputHandler::SCROLL_STARTED,
941 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
943 // Trying to scroll to the left/top will not succeed.
944 EXPECT_FALSE(
945 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
946 EXPECT_FALSE(
947 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
948 EXPECT_FALSE(
949 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
951 // Scrolling to the right/bottom will succeed.
952 EXPECT_TRUE(
953 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
954 EXPECT_TRUE(
955 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
956 EXPECT_TRUE(
957 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
959 // Scrolling to left/top will now 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 diagonally against an edge will succeed.
968 EXPECT_TRUE(
969 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
970 EXPECT_TRUE(
971 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
972 EXPECT_TRUE(
973 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
975 // Trying to scroll more than the available space will also succeed.
976 EXPECT_TRUE(
977 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
980 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
981 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
982 host_impl_->SetViewportSize(gfx::Size(100, 1000));
984 DrawFrame();
986 EXPECT_EQ(InputHandler::SCROLL_STARTED,
987 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
989 // Trying to scroll without a vertical scrollbar will fail.
990 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
991 gfx::Point(), SCROLL_FORWARD));
992 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
993 gfx::Point(), SCROLL_BACKWARD));
995 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
996 PaintedScrollbarLayerImpl::Create(
997 host_impl_->active_tree(),
999 VERTICAL));
1000 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
1001 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
1002 vertical_scrollbar.get());
1004 // Trying to scroll with a vertical scrollbar will succeed.
1005 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1006 gfx::Point(), SCROLL_FORWARD));
1007 EXPECT_FLOAT_EQ(875.f,
1008 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
1009 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1010 gfx::Point(), SCROLL_BACKWARD));
1013 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
1014 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
1015 host_impl_->SetViewportSize(gfx::Size(100, 100));
1017 gfx::Size overflow_size(400, 400);
1018 ASSERT_EQ(1u, scroll_layer->children().size());
1019 LayerImpl* overflow = scroll_layer->children()[0];
1020 overflow->SetBounds(overflow_size);
1021 overflow->SetContentBounds(overflow_size);
1022 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
1023 overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1024 overflow->SetPosition(gfx::PointF());
1026 DrawFrame();
1027 gfx::Point scroll_position(10, 10);
1029 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1030 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1031 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1032 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
1034 gfx::Vector2dF scroll_delta(10, 10);
1035 host_impl_->ScrollBy(scroll_position, scroll_delta);
1036 host_impl_->ScrollEnd();
1037 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1038 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1040 overflow->set_user_scrollable_horizontal(false);
1042 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1043 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1044 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1045 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1047 host_impl_->ScrollBy(scroll_position, scroll_delta);
1048 host_impl_->ScrollEnd();
1049 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1050 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1052 overflow->set_user_scrollable_vertical(false);
1054 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1055 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1056 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1057 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1059 host_impl_->ScrollBy(scroll_position, scroll_delta);
1060 host_impl_->ScrollEnd();
1061 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
1062 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1065 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
1066 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
1067 host_impl_->SetViewportSize(gfx::Size(50, 50));
1068 DrawFrame();
1070 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
1071 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
1072 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1074 float min_page_scale = 1.f, max_page_scale = 4.f;
1075 float page_scale_factor = 1.f;
1077 // The impl-based pinch zoom should adjust the max scroll position.
1079 host_impl_->active_tree()->PushPageScaleFromMainThread(
1080 page_scale_factor, min_page_scale, max_page_scale);
1081 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1082 scroll_layer->SetScrollDelta(gfx::Vector2d());
1084 float page_scale_delta = 2.f;
1086 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1087 host_impl_->PinchGestureBegin();
1088 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1089 host_impl_->PinchGestureEnd();
1090 host_impl_->ScrollEnd();
1091 EXPECT_FALSE(did_request_animate_);
1092 EXPECT_TRUE(did_request_redraw_);
1093 EXPECT_TRUE(did_request_commit_);
1094 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1096 scoped_ptr<ScrollAndScaleSet> scroll_info =
1097 host_impl_->ProcessScrollDeltas();
1098 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1100 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1101 scroll_layer->MaxScrollOffset().ToString());
1104 // Scrolling after a pinch gesture should always be in local space. The
1105 // scroll deltas have the page scale factor applied.
1107 host_impl_->active_tree()->PushPageScaleFromMainThread(
1108 page_scale_factor, min_page_scale, max_page_scale);
1109 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1110 scroll_layer->SetScrollDelta(gfx::Vector2d());
1112 float page_scale_delta = 2.f;
1113 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1114 host_impl_->PinchGestureBegin();
1115 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1116 host_impl_->PinchGestureEnd();
1117 host_impl_->ScrollEnd();
1119 gfx::Vector2d scroll_delta(0, 10);
1120 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1121 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
1122 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1123 host_impl_->ScrollEnd();
1125 scoped_ptr<ScrollAndScaleSet> scroll_info =
1126 host_impl_->ProcessScrollDeltas();
1127 ExpectContains(*scroll_info.get(), scroll_layer->id(),
1128 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta));
1132 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
1133 ui::LatencyInfo latency_info;
1134 latency_info.trace_id = 1234;
1135 scoped_ptr<SwapPromise> swap_promise(
1136 new LatencyInfoSwapPromise(latency_info));
1138 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1139 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1140 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
1141 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1142 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
1143 host_impl_->ScrollEnd();
1145 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1146 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1147 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
1150 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1151 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1152 host_impl_->SetViewportSize(gfx::Size(50, 50));
1153 DrawFrame();
1155 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1156 DCHECK(scroll_layer);
1158 float min_page_scale = 1.f;
1159 float max_page_scale = 4.f;
1161 // Basic pinch zoom in gesture
1163 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1164 max_page_scale);
1165 scroll_layer->SetScrollDelta(gfx::Vector2d());
1167 float page_scale_delta = 2.f;
1168 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1169 host_impl_->PinchGestureBegin();
1170 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1171 host_impl_->PinchGestureEnd();
1172 host_impl_->ScrollEnd();
1173 EXPECT_FALSE(did_request_animate_);
1174 EXPECT_TRUE(did_request_redraw_);
1175 EXPECT_TRUE(did_request_commit_);
1177 scoped_ptr<ScrollAndScaleSet> scroll_info =
1178 host_impl_->ProcessScrollDeltas();
1179 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1182 // Zoom-in clamping
1184 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1185 max_page_scale);
1186 scroll_layer->SetScrollDelta(gfx::Vector2d());
1187 float page_scale_delta = 10.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();
1195 scoped_ptr<ScrollAndScaleSet> scroll_info =
1196 host_impl_->ProcessScrollDeltas();
1197 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1200 // Zoom-out clamping
1202 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1203 max_page_scale);
1204 scroll_layer->SetScrollDelta(gfx::Vector2d());
1205 scroll_layer->PullDeltaForMainThread();
1206 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1208 float page_scale_delta = 0.1f;
1209 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1210 host_impl_->PinchGestureBegin();
1211 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1212 host_impl_->PinchGestureEnd();
1213 host_impl_->ScrollEnd();
1215 scoped_ptr<ScrollAndScaleSet> scroll_info =
1216 host_impl_->ProcessScrollDeltas();
1217 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1219 EXPECT_TRUE(scroll_info->scrolls.empty());
1222 // Two-finger panning should not happen based on pinch events only
1224 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1225 max_page_scale);
1226 scroll_layer->SetScrollDelta(gfx::Vector2d());
1227 scroll_layer->PullDeltaForMainThread();
1228 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1230 float page_scale_delta = 1.f;
1231 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1232 host_impl_->PinchGestureBegin();
1233 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1234 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1235 host_impl_->PinchGestureEnd();
1236 host_impl_->ScrollEnd();
1238 scoped_ptr<ScrollAndScaleSet> scroll_info =
1239 host_impl_->ProcessScrollDeltas();
1240 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1241 EXPECT_TRUE(scroll_info->scrolls.empty());
1244 // Two-finger panning should work with interleaved scroll events
1246 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1247 max_page_scale);
1248 scroll_layer->SetScrollDelta(gfx::Vector2d());
1249 scroll_layer->PullDeltaForMainThread();
1250 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1252 float page_scale_delta = 1.f;
1253 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1254 host_impl_->PinchGestureBegin();
1255 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1256 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1257 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1258 host_impl_->PinchGestureEnd();
1259 host_impl_->ScrollEnd();
1261 scoped_ptr<ScrollAndScaleSet> scroll_info =
1262 host_impl_->ProcessScrollDeltas();
1263 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1264 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-10, -10));
1267 // Two-finger panning should work when starting fully zoomed out.
1269 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1270 scroll_layer->SetScrollDelta(gfx::Vector2d());
1271 scroll_layer->PullDeltaForMainThread();
1272 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1274 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1275 host_impl_->PinchGestureBegin();
1276 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1277 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1278 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1279 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1280 host_impl_->PinchGestureEnd();
1281 host_impl_->ScrollEnd();
1283 scoped_ptr<ScrollAndScaleSet> scroll_info =
1284 host_impl_->ProcessScrollDeltas();
1285 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1286 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(20, 20));
1290 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1291 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1292 host_impl_->SetViewportSize(gfx::Size(50, 50));
1293 DrawFrame();
1295 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1296 DCHECK(scroll_layer);
1298 float min_page_scale = 0.5f;
1299 float max_page_scale = 4.f;
1300 base::TimeTicks start_time = base::TimeTicks() +
1301 base::TimeDelta::FromSeconds(1);
1302 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1303 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1304 base::TimeTicks end_time = start_time + duration;
1306 // Non-anchor zoom-in
1308 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1309 max_page_scale);
1310 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1312 did_request_redraw_ = false;
1313 did_request_animate_ = false;
1314 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1315 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1316 gfx::Vector2d(),
1317 false,
1318 2.f,
1319 duration)));
1320 host_impl_->ActivateSyncTree();
1321 EXPECT_FALSE(did_request_redraw_);
1322 EXPECT_TRUE(did_request_animate_);
1324 did_request_redraw_ = false;
1325 did_request_animate_ = false;
1326 host_impl_->Animate(start_time);
1327 EXPECT_TRUE(did_request_redraw_);
1328 EXPECT_TRUE(did_request_animate_);
1330 did_request_redraw_ = false;
1331 did_request_animate_ = false;
1332 host_impl_->Animate(halfway_through_animation);
1333 EXPECT_TRUE(did_request_redraw_);
1334 EXPECT_TRUE(did_request_animate_);
1336 did_request_redraw_ = false;
1337 did_request_animate_ = false;
1338 did_request_commit_ = false;
1339 host_impl_->Animate(end_time);
1340 EXPECT_TRUE(did_request_commit_);
1341 EXPECT_FALSE(did_request_animate_);
1343 scoped_ptr<ScrollAndScaleSet> scroll_info =
1344 host_impl_->ProcessScrollDeltas();
1345 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1346 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1349 // Anchor zoom-out
1351 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1352 max_page_scale);
1353 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1355 did_request_redraw_ = false;
1356 did_request_animate_ = false;
1357 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1358 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1359 gfx::Vector2d(25, 25),
1360 true,
1361 min_page_scale,
1362 duration)));
1363 host_impl_->ActivateSyncTree();
1364 EXPECT_FALSE(did_request_redraw_);
1365 EXPECT_TRUE(did_request_animate_);
1367 did_request_redraw_ = false;
1368 did_request_animate_ = false;
1369 host_impl_->Animate(start_time);
1370 EXPECT_TRUE(did_request_redraw_);
1371 EXPECT_TRUE(did_request_animate_);
1373 did_request_redraw_ = false;
1374 did_request_commit_ = false;
1375 did_request_animate_ = false;
1376 host_impl_->Animate(end_time);
1377 EXPECT_TRUE(did_request_redraw_);
1378 EXPECT_FALSE(did_request_animate_);
1379 EXPECT_TRUE(did_request_commit_);
1381 scoped_ptr<ScrollAndScaleSet> scroll_info =
1382 host_impl_->ProcessScrollDeltas();
1383 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1384 // Pushed to (0,0) via clamping against contents layer size.
1385 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1389 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1390 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1391 host_impl_->SetViewportSize(gfx::Size(50, 50));
1392 DrawFrame();
1394 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1395 DCHECK(scroll_layer);
1397 float min_page_scale = 0.5f;
1398 float max_page_scale = 4.f;
1399 base::TimeTicks start_time = base::TimeTicks() +
1400 base::TimeDelta::FromSeconds(1);
1401 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1402 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1403 base::TimeTicks end_time = start_time + duration;
1405 // Anchor zoom with unchanged page scale should not change scroll or scale.
1407 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1408 max_page_scale);
1409 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1411 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1412 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1413 gfx::Vector2d(),
1414 true,
1415 1.f,
1416 duration)));
1417 host_impl_->ActivateSyncTree();
1418 host_impl_->Animate(start_time);
1419 host_impl_->Animate(halfway_through_animation);
1420 EXPECT_TRUE(did_request_redraw_);
1421 host_impl_->Animate(end_time);
1422 EXPECT_TRUE(did_request_commit_);
1424 scoped_ptr<ScrollAndScaleSet> scroll_info =
1425 host_impl_->ProcessScrollDeltas();
1426 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1427 ExpectNone(*scroll_info, scroll_layer->id());
1431 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1432 host_impl_->CreatePendingTree();
1433 CreateScrollAndContentsLayers(
1434 host_impl_->pending_tree(),
1435 gfx::Size(100, 100));
1436 host_impl_->ActivateSyncTree();
1437 DrawFrame();
1439 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1440 DCHECK(scroll_layer);
1442 float min_page_scale = 0.5f;
1443 float max_page_scale = 4.f;
1444 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1445 max_page_scale);
1446 host_impl_->ActivateSyncTree();
1448 base::TimeTicks start_time = base::TimeTicks() +
1449 base::TimeDelta::FromSeconds(1);
1450 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1451 base::TimeTicks third_through_animation = start_time + duration / 3;
1452 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1453 base::TimeTicks end_time = start_time + duration;
1454 float target_scale = 2.f;
1456 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1458 // Make sure TakePageScaleAnimation works properly.
1460 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1461 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1462 gfx::Vector2d(),
1463 false,
1464 target_scale,
1465 duration)));
1466 scoped_ptr<PendingPageScaleAnimation> psa =
1467 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1468 EXPECT_EQ(target_scale, psa->scale);
1469 EXPECT_EQ(duration, psa->duration);
1470 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1472 // Recreate the PSA. Nothing should happen here since the tree containing the
1473 // PSA hasn't been activated yet.
1474 did_request_redraw_ = false;
1475 did_request_animate_ = false;
1476 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1477 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1478 gfx::Vector2d(),
1479 false,
1480 target_scale,
1481 duration)));
1482 host_impl_->Animate(halfway_through_animation);
1483 EXPECT_FALSE(did_request_animate_);
1484 EXPECT_FALSE(did_request_redraw_);
1486 // Activate the sync tree. This should cause the animation to become enabled.
1487 // It should also clear the pointer on the sync tree.
1488 host_impl_->ActivateSyncTree();
1489 EXPECT_EQ(nullptr,
1490 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1491 EXPECT_FALSE(did_request_redraw_);
1492 EXPECT_TRUE(did_request_animate_);
1494 // From here on, make sure the animation runs as normal.
1495 did_request_redraw_ = false;
1496 did_request_animate_ = false;
1497 host_impl_->Animate(start_time);
1498 EXPECT_TRUE(did_request_redraw_);
1499 EXPECT_TRUE(did_request_animate_);
1501 did_request_redraw_ = false;
1502 did_request_animate_ = false;
1503 host_impl_->Animate(third_through_animation);
1504 EXPECT_TRUE(did_request_redraw_);
1505 EXPECT_TRUE(did_request_animate_);
1507 // Another activation shouldn't have any effect on the animation.
1508 host_impl_->ActivateSyncTree();
1510 did_request_redraw_ = false;
1511 did_request_animate_ = false;
1512 host_impl_->Animate(halfway_through_animation);
1513 EXPECT_TRUE(did_request_redraw_);
1514 EXPECT_TRUE(did_request_animate_);
1516 did_request_redraw_ = false;
1517 did_request_animate_ = false;
1518 did_request_commit_ = false;
1519 host_impl_->Animate(end_time);
1520 EXPECT_TRUE(did_request_commit_);
1521 EXPECT_FALSE(did_request_animate_);
1523 scoped_ptr<ScrollAndScaleSet> scroll_info =
1524 host_impl_->ProcessScrollDeltas();
1525 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
1526 ExpectContains(*scroll_info, scroll_layer->id(), gfx::Vector2d(-50, -50));
1529 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
1530 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1531 host_impl_->SetViewportSize(gfx::Size(50, 50));
1532 DrawFrame();
1534 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1535 DCHECK(scroll_layer);
1537 base::TimeTicks start_time =
1538 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1539 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1540 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1541 base::TimeTicks end_time = start_time + duration;
1543 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1544 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1546 did_complete_page_scale_animation_ = false;
1547 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1548 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1549 gfx::Vector2d(), false, 2.f, duration)));
1550 host_impl_->ActivateSyncTree();
1551 host_impl_->Animate(start_time);
1552 EXPECT_FALSE(did_complete_page_scale_animation_);
1554 host_impl_->Animate(halfway_through_animation);
1555 EXPECT_FALSE(did_complete_page_scale_animation_);
1557 host_impl_->Animate(end_time);
1558 EXPECT_TRUE(did_complete_page_scale_animation_);
1561 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1562 public:
1563 LayerTreeHostImplOverridePhysicalTime(
1564 const LayerTreeSettings& settings,
1565 LayerTreeHostImplClient* client,
1566 Proxy* proxy,
1567 SharedBitmapManager* manager,
1568 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1569 : LayerTreeHostImpl(settings,
1570 client,
1571 proxy,
1572 rendering_stats_instrumentation,
1573 manager,
1574 NULL,
1575 NULL,
1576 0) {}
1578 BeginFrameArgs CurrentBeginFrameArgs() const override {
1579 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
1580 fake_current_physical_time_);
1583 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1584 fake_current_physical_time_ = fake_now;
1587 private:
1588 base::TimeTicks fake_current_physical_time_;
1591 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
1592 protected:
1593 void SetupLayers(LayerTreeSettings settings) {
1594 gfx::Size viewport_size(10, 10);
1595 gfx::Size content_size(100, 100);
1597 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1598 new LayerTreeHostImplOverridePhysicalTime(settings, this, &proxy_,
1599 shared_bitmap_manager_.get(),
1600 &stats_instrumentation_);
1601 host_impl_ = make_scoped_ptr(host_impl_override_time);
1602 host_impl_->InitializeRenderer(CreateOutputSurface());
1603 host_impl_->SetViewportSize(viewport_size);
1605 scoped_ptr<LayerImpl> root =
1606 LayerImpl::Create(host_impl_->active_tree(), 1);
1607 root->SetBounds(viewport_size);
1609 scoped_ptr<LayerImpl> scroll =
1610 LayerImpl::Create(host_impl_->active_tree(), 2);
1611 scroll->SetScrollClipLayer(root->id());
1612 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1613 root->SetBounds(viewport_size);
1614 scroll->SetBounds(content_size);
1615 scroll->SetContentBounds(content_size);
1616 scroll->SetIsContainerForFixedPositionLayers(true);
1618 scoped_ptr<LayerImpl> contents =
1619 LayerImpl::Create(host_impl_->active_tree(), 3);
1620 contents->SetDrawsContent(true);
1621 contents->SetBounds(content_size);
1622 contents->SetContentBounds(content_size);
1624 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
1625 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,
1626 VERTICAL, 10, 0, false, true);
1627 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
1629 scroll->AddChild(contents.Pass());
1630 root->AddChild(scroll.Pass());
1631 root->SetHasRenderSurface(true);
1632 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1633 root->AddChild(scrollbar.Pass());
1635 host_impl_->active_tree()->SetRootLayer(root.Pass());
1636 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1637 Layer::INVALID_ID);
1638 host_impl_->active_tree()->DidBecomeActive();
1639 DrawFrame();
1642 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
1643 LayerTreeSettings settings;
1644 settings.scrollbar_animator = animator;
1645 settings.scrollbar_fade_delay_ms = 20;
1646 settings.scrollbar_fade_duration_ms = 20;
1648 SetupLayers(settings);
1650 base::TimeTicks fake_now = gfx::FrameTime::Now();
1652 EXPECT_FALSE(did_request_animate_);
1653 EXPECT_FALSE(did_request_redraw_);
1654 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1655 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1657 // If no scroll happened during a scroll gesture, it should have no effect.
1658 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1659 host_impl_->ScrollEnd();
1660 EXPECT_FALSE(did_request_animate_);
1661 EXPECT_FALSE(did_request_redraw_);
1662 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1663 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1665 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1666 // now.
1667 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1668 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1669 EXPECT_FALSE(did_request_animate_);
1670 EXPECT_TRUE(did_request_redraw_);
1671 did_request_redraw_ = false;
1672 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1673 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1675 host_impl_->ScrollEnd();
1676 EXPECT_FALSE(did_request_animate_);
1677 EXPECT_FALSE(did_request_redraw_);
1678 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1679 requested_animation_delay_);
1680 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1682 fake_now += requested_animation_delay_;
1683 requested_animation_delay_ = base::TimeDelta();
1684 animation_task_.Run();
1685 animation_task_ = base::Closure();
1686 EXPECT_TRUE(did_request_animate_);
1687 did_request_animate_ = false;
1688 EXPECT_FALSE(did_request_redraw_);
1690 // After the scrollbar animation begins, we should start getting redraws.
1691 host_impl_->Animate(fake_now);
1692 EXPECT_TRUE(did_request_animate_);
1693 did_request_animate_ = false;
1694 EXPECT_TRUE(did_request_redraw_);
1695 did_request_redraw_ = false;
1696 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1697 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1699 // Setting the scroll offset outside a scroll should also cause the
1700 // scrollbar to appear and to schedule a scrollbar animation.
1701 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1702 gfx::ScrollOffset(5, 5));
1703 EXPECT_FALSE(did_request_animate_);
1704 EXPECT_FALSE(did_request_redraw_);
1705 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1706 requested_animation_delay_);
1707 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1708 requested_animation_delay_ = base::TimeDelta();
1709 animation_task_ = base::Closure();
1711 // Scrollbar animation is not triggered unnecessarily.
1712 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1713 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1714 EXPECT_FALSE(did_request_animate_);
1715 EXPECT_TRUE(did_request_redraw_);
1716 did_request_redraw_ = false;
1717 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1718 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1720 host_impl_->ScrollEnd();
1721 EXPECT_FALSE(did_request_animate_);
1722 EXPECT_FALSE(did_request_redraw_);
1723 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1724 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1726 // Changing page scale triggers scrollbar animation.
1727 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
1728 host_impl_->SetPageScaleOnActiveTree(1.1f);
1729 EXPECT_FALSE(did_request_animate_);
1730 EXPECT_FALSE(did_request_redraw_);
1731 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1732 requested_animation_delay_);
1733 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1734 requested_animation_delay_ = base::TimeDelta();
1735 animation_task_ = base::Closure();
1739 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
1740 RunTest(LayerTreeSettings::LINEAR_FADE);
1743 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
1744 RunTest(LayerTreeSettings::THINNING);
1747 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1748 float device_scale_factor) {
1749 LayerTreeSettings settings;
1750 settings.scrollbar_fade_delay_ms = 500;
1751 settings.scrollbar_fade_duration_ms = 300;
1752 settings.scrollbar_animator = LayerTreeSettings::THINNING;
1754 gfx::Size viewport_size(300, 200);
1755 gfx::Size device_viewport_size = gfx::ToFlooredSize(
1756 gfx::ScaleSize(viewport_size, device_scale_factor));
1757 gfx::Size content_size(1000, 1000);
1759 CreateHostImpl(settings, CreateOutputSurface());
1760 host_impl_->SetDeviceScaleFactor(device_scale_factor);
1761 host_impl_->SetViewportSize(device_viewport_size);
1763 scoped_ptr<LayerImpl> root =
1764 LayerImpl::Create(host_impl_->active_tree(), 1);
1765 root->SetBounds(viewport_size);
1766 root->SetHasRenderSurface(true);
1768 scoped_ptr<LayerImpl> scroll =
1769 LayerImpl::Create(host_impl_->active_tree(), 2);
1770 scroll->SetScrollClipLayer(root->id());
1771 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1772 scroll->SetBounds(content_size);
1773 scroll->SetContentBounds(content_size);
1774 scroll->SetIsContainerForFixedPositionLayers(true);
1776 scoped_ptr<LayerImpl> contents =
1777 LayerImpl::Create(host_impl_->active_tree(), 3);
1778 contents->SetDrawsContent(true);
1779 contents->SetBounds(content_size);
1780 contents->SetContentBounds(content_size);
1782 // The scrollbar is on the right side.
1783 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
1784 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
1785 scrollbar->SetDrawsContent(true);
1786 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
1787 scrollbar->SetContentBounds(gfx::Size(15, viewport_size.height()));
1788 scrollbar->SetPosition(gfx::Point(285, 0));
1790 scroll->AddChild(contents.Pass());
1791 root->AddChild(scroll.Pass());
1792 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1793 root->AddChild(scrollbar.Pass());
1795 host_impl_->active_tree()->SetRootLayer(root.Pass());
1796 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1797 Layer::INVALID_ID);
1798 host_impl_->active_tree()->DidBecomeActive();
1799 DrawFrame();
1801 LayerImpl* root_scroll =
1802 host_impl_->active_tree()->InnerViewportScrollLayer();
1803 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
1804 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
1805 static_cast<ScrollbarAnimationControllerThinning*>(
1806 root_scroll->scrollbar_animation_controller());
1807 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
1809 host_impl_->MouseMoveAt(gfx::Point(1, 1));
1810 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1812 host_impl_->MouseMoveAt(gfx::Point(200, 50));
1813 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1815 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1816 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1818 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
1819 host_impl_->MouseMoveAt(gfx::Point(184, 100));
1820 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
1822 did_request_redraw_ = false;
1823 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1824 host_impl_->MouseMoveAt(gfx::Point(290, 100));
1825 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1826 host_impl_->MouseMoveAt(gfx::Point(290, 120));
1827 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1828 host_impl_->MouseMoveAt(gfx::Point(150, 120));
1829 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
1832 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
1833 SetupMouseMoveAtWithDeviceScale(1.f);
1836 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
1837 SetupMouseMoveAtWithDeviceScale(2.f);
1840 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
1841 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1842 host_impl_->SetViewportSize(gfx::Size(50, 50));
1843 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1844 DrawFrame();
1846 CompositorFrameMetadata metadata =
1847 host_impl_->MakeCompositorFrameMetadata();
1848 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
1849 EXPECT_EQ(1.f, metadata.page_scale_factor);
1850 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
1851 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1852 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1853 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1854 EXPECT_FALSE(metadata.root_overflow_x_hidden);
1855 EXPECT_FALSE(metadata.root_overflow_y_hidden);
1858 // Scrolling should update metadata immediately.
1859 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1860 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
1861 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1863 CompositorFrameMetadata metadata =
1864 host_impl_->MakeCompositorFrameMetadata();
1865 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1867 host_impl_->ScrollEnd();
1869 CompositorFrameMetadata metadata =
1870 host_impl_->MakeCompositorFrameMetadata();
1871 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1874 // Root "overflow: hidden" properties should be reflected on the outer
1875 // viewport scroll layer.
1877 host_impl_->active_tree()
1878 ->OuterViewportScrollLayer()
1879 ->set_user_scrollable_horizontal(false);
1880 CompositorFrameMetadata metadata =
1881 host_impl_->MakeCompositorFrameMetadata();
1882 EXPECT_TRUE(metadata.root_overflow_x_hidden);
1883 EXPECT_FALSE(metadata.root_overflow_y_hidden);
1885 host_impl_->active_tree()
1886 ->OuterViewportScrollLayer()
1887 ->set_user_scrollable_vertical(false);
1888 metadata = host_impl_->MakeCompositorFrameMetadata();
1889 EXPECT_TRUE(metadata.root_overflow_x_hidden);
1890 EXPECT_TRUE(metadata.root_overflow_y_hidden);
1893 // Page scale should update metadata correctly (shrinking only the viewport).
1894 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1895 host_impl_->PinchGestureBegin();
1896 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
1897 host_impl_->PinchGestureEnd();
1898 host_impl_->ScrollEnd();
1900 CompositorFrameMetadata metadata =
1901 host_impl_->MakeCompositorFrameMetadata();
1902 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1903 EXPECT_EQ(2.f, metadata.page_scale_factor);
1904 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
1905 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1906 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1907 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1910 // Likewise if set from the main thread.
1911 host_impl_->ProcessScrollDeltas();
1912 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
1913 host_impl_->SetPageScaleOnActiveTree(4.f);
1915 CompositorFrameMetadata metadata =
1916 host_impl_->MakeCompositorFrameMetadata();
1917 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
1918 EXPECT_EQ(4.f, metadata.page_scale_factor);
1919 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
1920 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
1921 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
1922 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
1926 class DidDrawCheckLayer : public LayerImpl {
1927 public:
1928 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
1929 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
1932 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
1933 will_draw_called_ = true;
1934 if (will_draw_returns_false_)
1935 return false;
1936 return LayerImpl::WillDraw(draw_mode, provider);
1939 void AppendQuads(RenderPass* render_pass,
1940 AppendQuadsData* append_quads_data) override {
1941 append_quads_called_ = true;
1942 LayerImpl::AppendQuads(render_pass, append_quads_data);
1945 void DidDraw(ResourceProvider* provider) override {
1946 did_draw_called_ = true;
1947 LayerImpl::DidDraw(provider);
1950 bool will_draw_called() const { return will_draw_called_; }
1951 bool append_quads_called() const { return append_quads_called_; }
1952 bool did_draw_called() const { return did_draw_called_; }
1954 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
1956 void ClearDidDrawCheck() {
1957 will_draw_called_ = false;
1958 append_quads_called_ = false;
1959 did_draw_called_ = false;
1962 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
1964 void AddCopyRequest() {
1965 ScopedPtrVector<CopyOutputRequest> requests;
1966 requests.push_back(
1967 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
1968 SetHasRenderSurface(true);
1969 PassCopyRequests(&requests);
1972 protected:
1973 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
1974 : LayerImpl(tree_impl, id),
1975 will_draw_returns_false_(false),
1976 will_draw_called_(false),
1977 append_quads_called_(false),
1978 did_draw_called_(false) {
1979 SetBounds(gfx::Size(10, 10));
1980 SetContentBounds(gfx::Size(10, 10));
1981 SetDrawsContent(true);
1982 draw_properties().visible_content_rect = gfx::Rect(0, 0, 10, 10);
1985 private:
1986 bool will_draw_returns_false_;
1987 bool will_draw_called_;
1988 bool append_quads_called_;
1989 bool did_draw_called_;
1992 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
1993 // The root layer is always drawn, so run this test on a child layer that
1994 // will be masked out by the root layer's bounds.
1995 host_impl_->active_tree()->SetRootLayer(
1996 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
1997 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
1998 host_impl_->active_tree()->root_layer());
2000 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2001 root->SetHasRenderSurface(true);
2002 DidDrawCheckLayer* layer =
2003 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2006 LayerTreeHostImpl::FrameData frame;
2007 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2008 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2009 host_impl_->DidDrawAllLayers(frame);
2011 EXPECT_TRUE(layer->will_draw_called());
2012 EXPECT_TRUE(layer->append_quads_called());
2013 EXPECT_TRUE(layer->did_draw_called());
2016 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
2019 LayerTreeHostImpl::FrameData frame;
2021 layer->set_will_draw_returns_false();
2022 layer->ClearDidDrawCheck();
2024 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2025 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2026 host_impl_->DidDrawAllLayers(frame);
2028 EXPECT_TRUE(layer->will_draw_called());
2029 EXPECT_FALSE(layer->append_quads_called());
2030 EXPECT_FALSE(layer->did_draw_called());
2034 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
2035 // The root layer is always drawn, so run this test on a child layer that
2036 // will be masked out by the root layer's bounds.
2037 host_impl_->active_tree()->SetRootLayer(
2038 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2039 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2040 host_impl_->active_tree()->root_layer());
2041 root->SetMasksToBounds(true);
2042 root->SetHasRenderSurface(true);
2043 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2044 DidDrawCheckLayer* layer =
2045 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2046 // Ensure visible_content_rect for layer is empty.
2047 layer->SetPosition(gfx::PointF(100.f, 100.f));
2048 layer->SetBounds(gfx::Size(10, 10));
2049 layer->SetContentBounds(gfx::Size(10, 10));
2051 LayerTreeHostImpl::FrameData frame;
2053 EXPECT_FALSE(layer->will_draw_called());
2054 EXPECT_FALSE(layer->did_draw_called());
2056 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2057 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2058 host_impl_->DidDrawAllLayers(frame);
2060 EXPECT_FALSE(layer->will_draw_called());
2061 EXPECT_FALSE(layer->did_draw_called());
2063 EXPECT_TRUE(layer->visible_content_rect().IsEmpty());
2065 // Ensure visible_content_rect for layer is not empty
2066 layer->SetPosition(gfx::PointF());
2068 EXPECT_FALSE(layer->will_draw_called());
2069 EXPECT_FALSE(layer->did_draw_called());
2071 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2072 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2073 host_impl_->DidDrawAllLayers(frame);
2075 EXPECT_TRUE(layer->will_draw_called());
2076 EXPECT_TRUE(layer->did_draw_called());
2078 EXPECT_FALSE(layer->visible_content_rect().IsEmpty());
2081 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
2082 gfx::Size big_size(1000, 1000);
2083 host_impl_->SetViewportSize(big_size);
2085 host_impl_->active_tree()->SetRootLayer(
2086 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2087 DidDrawCheckLayer* root =
2088 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2090 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2091 DidDrawCheckLayer* occluded_layer =
2092 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2094 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2095 root->SetHasRenderSurface(true);
2096 DidDrawCheckLayer* top_layer =
2097 static_cast<DidDrawCheckLayer*>(root->children()[1]);
2098 // This layer covers the occluded_layer above. Make this layer large so it can
2099 // occlude.
2100 top_layer->SetBounds(big_size);
2101 top_layer->SetContentBounds(big_size);
2102 top_layer->SetContentsOpaque(true);
2104 LayerTreeHostImpl::FrameData frame;
2106 EXPECT_FALSE(occluded_layer->will_draw_called());
2107 EXPECT_FALSE(occluded_layer->did_draw_called());
2108 EXPECT_FALSE(top_layer->will_draw_called());
2109 EXPECT_FALSE(top_layer->did_draw_called());
2111 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2112 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2113 host_impl_->DidDrawAllLayers(frame);
2115 EXPECT_FALSE(occluded_layer->will_draw_called());
2116 EXPECT_FALSE(occluded_layer->did_draw_called());
2117 EXPECT_TRUE(top_layer->will_draw_called());
2118 EXPECT_TRUE(top_layer->did_draw_called());
2121 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
2122 host_impl_->active_tree()->SetRootLayer(
2123 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2124 DidDrawCheckLayer* root =
2125 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2127 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2128 root->SetHasRenderSurface(true);
2129 DidDrawCheckLayer* layer1 =
2130 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2132 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2133 DidDrawCheckLayer* layer2 =
2134 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
2136 layer1->SetHasRenderSurface(true);
2137 layer1->SetShouldFlattenTransform(true);
2139 EXPECT_FALSE(root->did_draw_called());
2140 EXPECT_FALSE(layer1->did_draw_called());
2141 EXPECT_FALSE(layer2->did_draw_called());
2143 LayerTreeHostImpl::FrameData frame;
2144 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2145 host_impl_->active_tree()->root_layer());
2146 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2147 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2148 host_impl_->DidDrawAllLayers(frame);
2150 EXPECT_TRUE(root->did_draw_called());
2151 EXPECT_TRUE(layer1->did_draw_called());
2152 EXPECT_TRUE(layer2->did_draw_called());
2154 EXPECT_NE(root->render_surface(), layer1->render_surface());
2155 EXPECT_TRUE(!!layer1->render_surface());
2158 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
2159 public:
2160 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2161 int id,
2162 bool tile_missing,
2163 bool had_incomplete_tile,
2164 bool animating,
2165 ResourceProvider* resource_provider) {
2166 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
2168 tile_missing,
2169 had_incomplete_tile,
2170 animating,
2171 resource_provider));
2174 void AppendQuads(RenderPass* render_pass,
2175 AppendQuadsData* append_quads_data) override {
2176 LayerImpl::AppendQuads(render_pass, append_quads_data);
2177 if (had_incomplete_tile_)
2178 append_quads_data->num_incomplete_tiles++;
2179 if (tile_missing_)
2180 append_quads_data->num_missing_tiles++;
2183 private:
2184 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
2185 int id,
2186 bool tile_missing,
2187 bool had_incomplete_tile,
2188 bool animating,
2189 ResourceProvider* resource_provider)
2190 : DidDrawCheckLayer(tree_impl, id),
2191 tile_missing_(tile_missing),
2192 had_incomplete_tile_(had_incomplete_tile) {
2193 if (animating)
2194 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2197 bool tile_missing_;
2198 bool had_incomplete_tile_;
2201 struct PrepareToDrawSuccessTestCase {
2202 struct State {
2203 bool has_missing_tile = false;
2204 bool has_incomplete_tile = false;
2205 bool is_animating = false;
2206 bool has_copy_request = false;
2208 bool high_res_required = false;
2209 State layer_before;
2210 State layer_between;
2211 State layer_after;
2212 DrawResult expected_result;
2214 explicit PrepareToDrawSuccessTestCase(DrawResult result)
2215 : expected_result(result) {}
2218 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
2219 std::vector<PrepareToDrawSuccessTestCase> cases;
2221 // 0. Default case.
2222 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2223 // 1. Animated layer first.
2224 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2225 cases.back().layer_before.is_animating = true;
2226 // 2. Animated layer between.
2227 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2228 cases.back().layer_between.is_animating = true;
2229 // 3. Animated layer last.
2230 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2231 cases.back().layer_after.is_animating = true;
2232 // 4. Missing tile first.
2233 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2234 cases.back().layer_before.has_missing_tile = true;
2235 // 5. Missing tile between.
2236 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2237 cases.back().layer_between.has_missing_tile = true;
2238 // 6. Missing tile last.
2239 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2240 cases.back().layer_after.has_missing_tile = true;
2241 // 7. Incomplete tile first.
2242 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2243 cases.back().layer_before.has_incomplete_tile = true;
2244 // 8. Incomplete tile between.
2245 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2246 cases.back().layer_between.has_incomplete_tile = true;
2247 // 9. Incomplete tile last.
2248 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2249 cases.back().layer_after.has_incomplete_tile = true;
2250 // 10. Animation with missing tile.
2251 cases.push_back(
2252 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
2253 cases.back().layer_between.has_missing_tile = true;
2254 cases.back().layer_between.is_animating = true;
2255 // 11. Animation with incomplete tile.
2256 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2257 cases.back().layer_between.has_incomplete_tile = true;
2258 cases.back().layer_between.is_animating = true;
2260 // 12. High res required.
2261 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2262 cases.back().high_res_required = true;
2263 // 13. High res required with incomplete tile.
2264 cases.push_back(
2265 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2266 cases.back().high_res_required = true;
2267 cases.back().layer_between.has_incomplete_tile = true;
2268 // 14. High res required with missing tile.
2269 cases.push_back(
2270 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2271 cases.back().high_res_required = true;
2272 cases.back().layer_between.has_missing_tile = true;
2274 // 15. High res required is higher priority than animating missing tiles.
2275 cases.push_back(
2276 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2277 cases.back().high_res_required = true;
2278 cases.back().layer_between.has_missing_tile = true;
2279 cases.back().layer_after.has_missing_tile = true;
2280 cases.back().layer_after.is_animating = true;
2281 // 16. High res required is higher priority than animating missing tiles.
2282 cases.push_back(
2283 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2284 cases.back().high_res_required = true;
2285 cases.back().layer_between.has_missing_tile = true;
2286 cases.back().layer_before.has_missing_tile = true;
2287 cases.back().layer_before.is_animating = true;
2289 host_impl_->active_tree()->SetRootLayer(
2290 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2291 DidDrawCheckLayer* root =
2292 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2293 root->SetHasRenderSurface(true);
2295 LayerTreeHostImpl::FrameData frame;
2296 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2297 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2298 host_impl_->DidDrawAllLayers(frame);
2299 host_impl_->SwapBuffers(frame);
2301 for (size_t i = 0; i < cases.size(); ++i) {
2302 const auto& testcase = cases[i];
2303 std::vector<LayerImpl*> to_remove;
2304 for (auto* child : root->children())
2305 to_remove.push_back(child);
2306 for (auto* child : to_remove)
2307 root->RemoveChild(child);
2309 std::ostringstream scope;
2310 scope << "Test case: " << i;
2311 SCOPED_TRACE(scope.str());
2313 root->AddChild(MissingTextureAnimatingLayer::Create(
2314 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2315 testcase.layer_before.has_incomplete_tile,
2316 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2317 DidDrawCheckLayer* before =
2318 static_cast<DidDrawCheckLayer*>(root->children().back());
2319 if (testcase.layer_before.has_copy_request)
2320 before->AddCopyRequest();
2322 root->AddChild(MissingTextureAnimatingLayer::Create(
2323 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2324 testcase.layer_between.has_incomplete_tile,
2325 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2326 DidDrawCheckLayer* between =
2327 static_cast<DidDrawCheckLayer*>(root->children().back());
2328 if (testcase.layer_between.has_copy_request)
2329 between->AddCopyRequest();
2331 root->AddChild(MissingTextureAnimatingLayer::Create(
2332 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2333 testcase.layer_after.has_incomplete_tile,
2334 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2335 DidDrawCheckLayer* after =
2336 static_cast<DidDrawCheckLayer*>(root->children().back());
2337 if (testcase.layer_after.has_copy_request)
2338 after->AddCopyRequest();
2340 if (testcase.high_res_required)
2341 host_impl_->SetRequiresHighResToDraw();
2343 LayerTreeHostImpl::FrameData frame;
2344 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2345 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2346 host_impl_->DidDrawAllLayers(frame);
2347 host_impl_->SwapBuffers(frame);
2351 TEST_F(LayerTreeHostImplTest,
2352 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
2353 CreateHostImpl(DefaultSettings(),
2354 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2355 EXPECT_TRUE(host_impl_->output_surface()
2356 ->capabilities()
2357 .draw_and_swap_full_viewport_every_frame);
2359 std::vector<PrepareToDrawSuccessTestCase> cases;
2361 // 0. Default case.
2362 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2363 // 1. Animation with missing tile.
2364 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2365 cases.back().layer_between.has_missing_tile = true;
2366 cases.back().layer_between.is_animating = true;
2367 // 2. High res required with incomplete tile.
2368 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2369 cases.back().high_res_required = true;
2370 cases.back().layer_between.has_incomplete_tile = true;
2371 // 3. High res required with missing tile.
2372 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2373 cases.back().high_res_required = true;
2374 cases.back().layer_between.has_missing_tile = true;
2376 host_impl_->active_tree()->SetRootLayer(
2377 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2378 DidDrawCheckLayer* root =
2379 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2380 root->SetHasRenderSurface(true);
2382 LayerTreeHostImpl::FrameData frame;
2383 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2384 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2385 host_impl_->DidDrawAllLayers(frame);
2386 host_impl_->SwapBuffers(frame);
2388 for (size_t i = 0; i < cases.size(); ++i) {
2389 const auto& testcase = cases[i];
2390 std::vector<LayerImpl*> to_remove;
2391 for (auto* child : root->children())
2392 to_remove.push_back(child);
2393 for (auto* child : to_remove)
2394 root->RemoveChild(child);
2396 std::ostringstream scope;
2397 scope << "Test case: " << i;
2398 SCOPED_TRACE(scope.str());
2400 root->AddChild(MissingTextureAnimatingLayer::Create(
2401 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2402 testcase.layer_before.has_incomplete_tile,
2403 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2404 DidDrawCheckLayer* before =
2405 static_cast<DidDrawCheckLayer*>(root->children().back());
2406 if (testcase.layer_before.has_copy_request)
2407 before->AddCopyRequest();
2409 root->AddChild(MissingTextureAnimatingLayer::Create(
2410 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2411 testcase.layer_between.has_incomplete_tile,
2412 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2413 DidDrawCheckLayer* between =
2414 static_cast<DidDrawCheckLayer*>(root->children().back());
2415 if (testcase.layer_between.has_copy_request)
2416 between->AddCopyRequest();
2418 root->AddChild(MissingTextureAnimatingLayer::Create(
2419 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2420 testcase.layer_after.has_incomplete_tile,
2421 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2422 DidDrawCheckLayer* after =
2423 static_cast<DidDrawCheckLayer*>(root->children().back());
2424 if (testcase.layer_after.has_copy_request)
2425 after->AddCopyRequest();
2427 if (testcase.high_res_required)
2428 host_impl_->SetRequiresHighResToDraw();
2430 LayerTreeHostImpl::FrameData frame;
2431 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2432 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
2433 host_impl_->DidDrawAllLayers(frame);
2434 host_impl_->SwapBuffers(frame);
2438 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2439 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2440 root->SetScrollClipLayer(Layer::INVALID_ID);
2441 root->SetHasRenderSurface(true);
2442 host_impl_->active_tree()->SetRootLayer(root.Pass());
2443 DrawFrame();
2445 // Scroll event is ignored because layer is not scrollable.
2446 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
2447 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2448 EXPECT_FALSE(did_request_redraw_);
2449 EXPECT_FALSE(did_request_commit_);
2452 // TODO(bokan): Convert these tests to create inner and outer viewports.
2453 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2454 public:
2455 LayerTreeHostImplTopControlsTest()
2456 // Make the clip size the same as the layer (content) size so the layer is
2457 // non-scrollable.
2458 : layer_size_(10, 10),
2459 clip_size_(layer_size_),
2460 top_controls_height_(50) {
2461 settings_.use_pinch_virtual_viewport = true;
2463 viewport_size_ = gfx::Size(clip_size_.width(),
2464 clip_size_.height() + top_controls_height_);
2467 bool CreateHostImpl(const LayerTreeSettings& settings,
2468 scoped_ptr<OutputSurface> output_surface) override {
2469 bool init =
2470 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
2471 if (init) {
2472 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
2473 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2475 return init;
2478 void SetupTopControlsAndScrollLayer() {
2479 scoped_ptr<LayerImpl> root =
2480 LayerImpl::Create(host_impl_->active_tree(), 1);
2481 scoped_ptr<LayerImpl> root_clip =
2482 LayerImpl::Create(host_impl_->active_tree(), 2);
2483 root_clip->SetBounds(clip_size_);
2484 root->SetScrollClipLayer(root_clip->id());
2485 root->SetBounds(layer_size_);
2486 root->SetContentBounds(layer_size_);
2487 root->SetPosition(gfx::PointF());
2488 root->SetDrawsContent(false);
2489 root->SetIsContainerForFixedPositionLayers(true);
2490 int inner_viewport_scroll_layer_id = root->id();
2491 int page_scale_layer_id = root_clip->id();
2492 root_clip->SetHasRenderSurface(true);
2493 root_clip->AddChild(root.Pass());
2494 root_clip->SetHasRenderSurface(true);
2495 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2496 host_impl_->active_tree()->SetViewportLayersFromIds(
2497 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2498 Layer::INVALID_ID);
2499 // Set a viewport size that is large enough to contain both the top controls
2500 // and some content.
2501 host_impl_->SetViewportSize(viewport_size_);
2502 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2504 host_impl_->DidChangeTopControlsPosition();
2506 host_impl_->CreatePendingTree();
2507 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2508 root =
2509 LayerImpl::Create(host_impl_->sync_tree(), 1);
2510 root_clip =
2511 LayerImpl::Create(host_impl_->sync_tree(), 2);
2512 root_clip->SetBounds(clip_size_);
2513 root->SetScrollClipLayer(root_clip->id());
2514 root->SetBounds(layer_size_);
2515 root->SetContentBounds(layer_size_);
2516 root->SetPosition(gfx::PointF());
2517 root->SetDrawsContent(false);
2518 root->SetIsContainerForFixedPositionLayers(true);
2519 inner_viewport_scroll_layer_id = root->id();
2520 page_scale_layer_id = root_clip->id();
2521 root_clip->AddChild(root.Pass());
2522 host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
2523 host_impl_->sync_tree()->SetViewportLayersFromIds(
2524 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2525 Layer::INVALID_ID);
2526 // Set a viewport size that is large enough to contain both the top controls
2527 // and some content.
2528 host_impl_->SetViewportSize(viewport_size_);
2529 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2530 host_impl_->DidChangeTopControlsPosition();
2533 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2534 const gfx::Size& inner_viewport_size,
2535 const gfx::Size& outer_viewport_size,
2536 const gfx::Size& scroll_layer_size) {
2537 CreateHostImpl(settings_, CreateOutputSurface());
2538 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2539 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2540 host_impl_->DidChangeTopControlsPosition();
2542 scoped_ptr<LayerImpl> root =
2543 LayerImpl::Create(host_impl_->active_tree(), 1);
2544 scoped_ptr<LayerImpl> root_clip =
2545 LayerImpl::Create(host_impl_->active_tree(), 2);
2546 scoped_ptr<LayerImpl> page_scale =
2547 LayerImpl::Create(host_impl_->active_tree(), 3);
2549 scoped_ptr<LayerImpl> outer_scroll =
2550 LayerImpl::Create(host_impl_->active_tree(), 4);
2551 scoped_ptr<LayerImpl> outer_clip =
2552 LayerImpl::Create(host_impl_->active_tree(), 5);
2554 root_clip->SetBounds(inner_viewport_size);
2555 root->SetScrollClipLayer(root_clip->id());
2556 root->SetBounds(outer_viewport_size);
2557 root->SetContentBounds(outer_viewport_size);
2558 root->SetPosition(gfx::PointF());
2559 root->SetDrawsContent(false);
2560 root->SetIsContainerForFixedPositionLayers(true);
2561 root_clip->SetHasRenderSurface(true);
2562 outer_clip->SetBounds(outer_viewport_size);
2563 outer_scroll->SetScrollClipLayer(outer_clip->id());
2564 outer_scroll->SetBounds(scroll_layer_size);
2565 outer_scroll->SetContentBounds(scroll_layer_size);
2566 outer_scroll->SetPosition(gfx::PointF());
2567 outer_scroll->SetDrawsContent(false);
2568 outer_scroll->SetIsContainerForFixedPositionLayers(true);
2570 int inner_viewport_scroll_layer_id = root->id();
2571 int outer_viewport_scroll_layer_id = outer_scroll->id();
2572 int page_scale_layer_id = page_scale->id();
2574 outer_clip->AddChild(outer_scroll.Pass());
2575 root->AddChild(outer_clip.Pass());
2576 page_scale->AddChild(root.Pass());
2577 root_clip->AddChild(page_scale.Pass());
2579 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2580 host_impl_->active_tree()->SetViewportLayersFromIds(
2581 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2582 outer_viewport_scroll_layer_id);
2584 host_impl_->SetViewportSize(inner_viewport_size);
2585 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2586 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
2589 protected:
2590 gfx::Size layer_size_;
2591 gfx::Size clip_size_;
2592 gfx::Size viewport_size_;
2593 float top_controls_height_;
2595 LayerTreeSettings settings_;
2596 }; // class LayerTreeHostImplTopControlsTest
2598 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2599 SetupTopControlsAndScrollLayerWithVirtualViewport(
2600 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2601 DrawFrame();
2603 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2604 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2606 // Make the test scroll delta a fractional amount, to verify that the
2607 // fixed container size delta is (1) non-zero, and (2) fractional, and
2608 // (3) matches the movement of the top controls.
2609 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2610 host_impl_->top_controls_manager()->ScrollBegin();
2611 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2612 host_impl_->top_controls_manager()->ScrollEnd();
2614 LayerImpl* inner_viewport_scroll_layer =
2615 host_impl_->active_tree()->InnerViewportScrollLayer();
2616 DCHECK(inner_viewport_scroll_layer);
2617 host_impl_->ScrollEnd();
2618 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
2619 inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
2622 // In this test, the outer viewport is initially unscrollable. We test that a
2623 // scroll initiated on the inner viewport, causing the top controls to show and
2624 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2625 TEST_F(LayerTreeHostImplTopControlsTest,
2626 TopControlsOuterViewportBecomesScrollable) {
2627 SetupTopControlsAndScrollLayerWithVirtualViewport(
2628 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2629 DrawFrame();
2631 LayerImpl *inner_scroll =
2632 host_impl_->active_tree()->InnerViewportScrollLayer();
2633 LayerImpl *inner_container =
2634 host_impl_->active_tree()->InnerViewportContainerLayer();
2635 LayerImpl *outer_scroll =
2636 host_impl_->active_tree()->OuterViewportScrollLayer();
2637 LayerImpl *outer_container =
2638 host_impl_->active_tree()->OuterViewportContainerLayer();
2640 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2641 outer_scroll->SetDrawsContent(true);
2642 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
2644 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2645 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2646 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
2648 // The entire scroll delta should have been used to hide the top controls.
2649 // The viewport layers should be resized back to their full sizes.
2650 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2651 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2652 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
2653 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
2655 // The inner viewport should be scrollable by 50px * page_scale.
2656 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
2657 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
2658 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2659 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
2661 host_impl_->ScrollEnd();
2663 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2664 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2665 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
2667 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2669 // The entire scroll delta should have been used to show the top controls.
2670 // The outer viewport should be resized to accomodate and scrolled to the
2671 // bottom of the document to keep the viewport in place.
2672 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2673 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
2674 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
2675 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
2676 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2678 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2679 // since it wasn't scrollable when the scroll began.
2680 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
2681 EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
2682 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2684 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
2685 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2686 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2688 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2689 host_impl_->ScrollEnd();
2691 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2692 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2695 // Test that the fixed position container delta is appropriately adjusted
2696 // by the top controls showing/hiding and page scale doesn't affect it.
2697 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
2698 SetupTopControlsAndScrollLayerWithVirtualViewport(
2699 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2700 DrawFrame();
2702 float page_scale = 1.5f;
2703 LayerImpl* outer_viewport_scroll_layer =
2704 host_impl_->active_tree()->OuterViewportScrollLayer();
2706 // Zoom in, since the fixed container is the outer viewport, the delta should
2707 // not be scaled.
2708 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
2710 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2711 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2713 // Scroll down, the top controls hiding should expand the viewport size so
2714 // the delta should be equal to the scroll distance.
2715 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
2716 host_impl_->top_controls_manager()->ScrollBegin();
2717 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2718 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
2719 host_impl_->top_controls_manager()->ContentTopOffset());
2720 EXPECT_VECTOR_EQ(top_controls_scroll_delta,
2721 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2722 host_impl_->ScrollEnd();
2724 // Scroll past the maximum extent. The delta shouldn't be greater than the
2725 // top controls height.
2726 host_impl_->top_controls_manager()->ScrollBegin();
2727 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2728 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2729 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2730 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2731 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
2732 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2733 host_impl_->ScrollEnd();
2735 // Scroll in the direction to make the top controls show.
2736 host_impl_->top_controls_manager()->ScrollBegin();
2737 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
2738 EXPECT_EQ(top_controls_scroll_delta.y(),
2739 host_impl_->top_controls_manager()->ContentTopOffset());
2740 EXPECT_VECTOR_EQ(
2741 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
2742 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2743 host_impl_->top_controls_manager()->ScrollEnd();
2746 // Test that if a scrollable sublayer doesn't consume the scroll,
2747 // top controls should hide when scrolling down.
2748 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
2749 gfx::Size sub_content_size(100, 400);
2750 gfx::Size sub_content_layer_size(100, 300);
2751 SetupTopControlsAndScrollLayerWithVirtualViewport(
2752 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
2753 DrawFrame();
2755 // Show top controls
2756 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2758 LayerImpl* outer_viewport_scroll_layer =
2759 host_impl_->active_tree()->OuterViewportScrollLayer();
2760 int id = outer_viewport_scroll_layer->id();
2762 scoped_ptr<LayerImpl> child =
2763 LayerImpl::Create(host_impl_->active_tree(), id + 2);
2764 scoped_ptr<LayerImpl> child_clip =
2765 LayerImpl::Create(host_impl_->active_tree(), id + 3);
2767 child_clip->SetBounds(sub_content_layer_size);
2768 child->SetScrollClipLayer(child_clip->id());
2769 child->SetBounds(sub_content_size);
2770 child->SetContentBounds(sub_content_size);
2771 child->SetPosition(gfx::PointF());
2772 child->SetDrawsContent(true);
2773 child->SetIsContainerForFixedPositionLayers(true);
2775 // scroll child to limit
2776 child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
2777 child_clip->AddChild(child.Pass());
2778 outer_viewport_scroll_layer->AddChild(child_clip.Pass());
2780 // Scroll 25px to hide top controls
2781 gfx::Vector2dF scroll_delta(0.f, 25.f);
2782 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2783 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2784 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2785 host_impl_->ScrollEnd();
2787 // Top controls should be hidden
2788 EXPECT_EQ(scroll_delta.y(),
2789 top_controls_height_ -
2790 host_impl_->top_controls_manager()->ContentTopOffset());
2793 // Ensure setting the top controls position explicitly using the setters on the
2794 // TreeImpl correctly affects the top controls manager and viewport bounds.
2795 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
2796 CreateHostImpl(settings_, CreateOutputSurface());
2797 SetupTopControlsAndScrollLayer();
2798 DrawFrame();
2800 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2801 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2802 30.f / top_controls_height_);
2803 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2804 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
2805 EXPECT_FLOAT_EQ(-20.f,
2806 host_impl_->top_controls_manager()->ControlsTopOffset());
2808 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2809 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2810 EXPECT_FLOAT_EQ(-50.f,
2811 host_impl_->top_controls_manager()->ControlsTopOffset());
2813 host_impl_->DidChangeTopControlsPosition();
2815 // Now that top controls have moved, expect the clip to resize.
2816 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2817 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2820 // Test that the top_controls delta and sent delta are appropriately
2821 // applied on sync tree activation. The total top controls offset shouldn't
2822 // change after the activation.
2823 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
2824 CreateHostImpl(settings_, CreateOutputSurface());
2825 SetupTopControlsAndScrollLayer();
2826 DrawFrame();
2828 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2829 20.f / top_controls_height_);
2830 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2831 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
2832 15.f / top_controls_height_);
2833 host_impl_->active_tree()
2834 ->top_controls_shown_ratio()
2835 ->PullDeltaForMainThread();
2836 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2837 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
2838 top_controls_height_);
2840 host_impl_->DidChangeTopControlsPosition();
2841 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2842 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2843 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2845 host_impl_->ActivateSyncTree();
2847 root_clip_ptr = host_impl_->active_tree()->root_layer();
2848 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2849 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2851 EXPECT_FLOAT_EQ(
2852 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
2853 top_controls_height_);
2854 EXPECT_FLOAT_EQ(
2855 15.f,
2856 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
2857 top_controls_height_);
2860 // Test that changing the top controls layout height is correctly applied to
2861 // the inner viewport container bounds. That is, the top controls layout
2862 // height is the amount that the inner viewport container was shrunk outside
2863 // the compositor to accommodate the top controls.
2864 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
2865 CreateHostImpl(settings_, CreateOutputSurface());
2866 SetupTopControlsAndScrollLayer();
2867 DrawFrame();
2869 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
2870 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2872 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2873 1.f);
2874 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2875 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
2877 host_impl_->DidChangeTopControlsPosition();
2878 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2879 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2880 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2882 host_impl_->sync_tree()->root_layer()->SetBounds(
2883 gfx::Size(root_clip_ptr->bounds().width(),
2884 root_clip_ptr->bounds().height() - 50.f));
2886 host_impl_->ActivateSyncTree();
2888 root_clip_ptr = host_impl_->active_tree()->root_layer();
2889 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2891 // The total bounds should remain unchanged since the bounds delta should
2892 // account for the difference between the layout height and the current
2893 // top controls offset.
2894 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
2895 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
2897 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2898 host_impl_->DidChangeTopControlsPosition();
2900 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
2901 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
2902 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
2903 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
2904 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
2905 root_clip_ptr->bounds());
2908 // Test that showing/hiding the top controls when the viewport is fully scrolled
2909 // doesn't incorrectly change the viewport offset due to clamping from changing
2910 // viewport bounds.
2911 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
2912 SetupTopControlsAndScrollLayerWithVirtualViewport(
2913 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2914 DrawFrame();
2916 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2918 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
2919 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
2921 // Scroll the viewports to max scroll offset.
2922 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2923 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2925 gfx::ScrollOffset viewport_offset =
2926 host_impl_->active_tree()->TotalScrollOffset();
2927 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
2929 // Hide the top controls by 25px.
2930 gfx::Vector2dF scroll_delta(0.f, 25.f);
2931 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2932 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2933 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2935 // scrolling down at the max extents no longer hides the top controls
2936 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2938 // forcefully hide the top controls by 25px
2939 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
2940 host_impl_->ScrollEnd();
2942 EXPECT_FLOAT_EQ(scroll_delta.y(),
2943 top_controls_height_ -
2944 host_impl_->top_controls_manager()->ContentTopOffset());
2946 inner_scroll->ClampScrollToMaxScrollOffset();
2947 outer_scroll->ClampScrollToMaxScrollOffset();
2949 // We should still be fully scrolled.
2950 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2951 host_impl_->active_tree()->TotalScrollOffset());
2953 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
2955 // Bring the top controls down by 25px.
2956 scroll_delta = gfx::Vector2dF(0.f, -25.f);
2957 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2958 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2959 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2960 host_impl_->ScrollEnd();
2962 // The viewport offset shouldn't have changed.
2963 EXPECT_EQ(viewport_offset,
2964 host_impl_->active_tree()->TotalScrollOffset());
2966 // Scroll the viewports to max scroll offset.
2967 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
2968 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
2969 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
2970 host_impl_->active_tree()->TotalScrollOffset());
2973 // Test that the top controls coming in and out maintains the same aspect ratio
2974 // between the inner and outer viewports.
2975 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
2976 SetupTopControlsAndScrollLayerWithVirtualViewport(
2977 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2978 DrawFrame();
2980 EXPECT_FLOAT_EQ(top_controls_height_,
2981 host_impl_->top_controls_manager()->ContentTopOffset());
2983 gfx::Vector2dF scroll_delta(0.f, 25.f);
2984 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2985 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2986 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
2987 host_impl_->ScrollEnd();
2989 EXPECT_FLOAT_EQ(scroll_delta.y(),
2990 top_controls_height_ -
2991 host_impl_->top_controls_manager()->ContentTopOffset());
2993 // Top controls were hidden by 25px so the inner viewport should have expanded
2994 // by that much.
2995 LayerImpl* outer_container =
2996 host_impl_->active_tree()->OuterViewportContainerLayer();
2997 LayerImpl* inner_container =
2998 host_impl_->active_tree()->InnerViewportContainerLayer();
2999 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
3001 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3002 float aspect_ratio = inner_container->BoundsForScrolling().width() /
3003 inner_container->BoundsForScrolling().height();
3004 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
3005 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
3006 EXPECT_EQ(expected,
3007 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
3010 // Test that scrolling the outer viewport affects the top controls.
3011 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
3012 SetupTopControlsAndScrollLayerWithVirtualViewport(
3013 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3014 DrawFrame();
3016 EXPECT_EQ(top_controls_height_,
3017 host_impl_->top_controls_manager()->ContentTopOffset());
3019 // Send a gesture scroll that will scroll the outer viewport, make sure the
3020 // top controls get scrolled.
3021 gfx::Vector2dF scroll_delta(0.f, 15.f);
3022 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3023 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3024 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3025 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3026 host_impl_->CurrentlyScrollingLayer());
3027 host_impl_->ScrollEnd();
3029 EXPECT_FLOAT_EQ(scroll_delta.y(),
3030 top_controls_height_ -
3031 host_impl_->top_controls_manager()->ContentTopOffset());
3033 scroll_delta = gfx::Vector2dF(0.f, 50.f);
3034 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3035 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3036 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3038 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
3039 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3040 host_impl_->CurrentlyScrollingLayer());
3042 host_impl_->ScrollEnd();
3044 // Position the viewports such that the inner viewport will be scrolled.
3045 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
3046 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3047 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
3049 scroll_delta = gfx::Vector2dF(0.f, -65.f);
3050 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3051 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3052 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3054 EXPECT_EQ(top_controls_height_,
3055 host_impl_->top_controls_manager()->ContentTopOffset());
3056 EXPECT_FLOAT_EQ(
3057 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
3058 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
3060 host_impl_->ScrollEnd();
3063 TEST_F(LayerTreeHostImplTopControlsTest,
3064 ScrollNonScrollableRootWithTopControls) {
3065 CreateHostImpl(settings_, CreateOutputSurface());
3066 SetupTopControlsAndScrollLayer();
3067 DrawFrame();
3069 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3070 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3072 host_impl_->top_controls_manager()->ScrollBegin();
3073 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
3074 host_impl_->top_controls_manager()->ScrollEnd();
3075 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3076 // Now that top controls have moved, expect the clip to resize.
3077 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3078 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3080 host_impl_->ScrollEnd();
3082 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3083 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3085 float scroll_increment_y = -25.f;
3086 host_impl_->top_controls_manager()->ScrollBegin();
3087 host_impl_->top_controls_manager()->ScrollBy(
3088 gfx::Vector2dF(0.f, scroll_increment_y));
3089 EXPECT_FLOAT_EQ(-scroll_increment_y,
3090 host_impl_->top_controls_manager()->ContentTopOffset());
3091 // Now that top controls have moved, expect the clip to resize.
3092 EXPECT_EQ(gfx::Size(viewport_size_.width(),
3093 viewport_size_.height() + scroll_increment_y),
3094 root_clip_ptr->bounds());
3096 host_impl_->top_controls_manager()->ScrollBy(
3097 gfx::Vector2dF(0.f, scroll_increment_y));
3098 host_impl_->top_controls_manager()->ScrollEnd();
3099 EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
3100 host_impl_->top_controls_manager()->ContentTopOffset());
3101 // Now that top controls have moved, expect the clip to resize.
3102 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
3104 host_impl_->ScrollEnd();
3106 // Verify the layer is once-again non-scrollable.
3107 EXPECT_EQ(
3108 gfx::ScrollOffset(),
3109 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3111 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3112 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3115 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
3116 // Test the configuration where a non-composited root layer is embedded in a
3117 // scrollable outer layer.
3118 gfx::Size surface_size(10, 10);
3119 gfx::Size contents_size(20, 20);
3121 scoped_ptr<LayerImpl> content_layer =
3122 LayerImpl::Create(host_impl_->active_tree(), 1);
3123 content_layer->SetDrawsContent(true);
3124 content_layer->SetPosition(gfx::PointF());
3125 content_layer->SetBounds(contents_size);
3126 content_layer->SetContentBounds(contents_size);
3127 content_layer->SetContentsScale(2.f, 2.f);
3129 scoped_ptr<LayerImpl> scroll_clip_layer =
3130 LayerImpl::Create(host_impl_->active_tree(), 3);
3131 scroll_clip_layer->SetBounds(surface_size);
3133 scoped_ptr<LayerImpl> scroll_layer =
3134 LayerImpl::Create(host_impl_->active_tree(), 2);
3135 scroll_layer->SetScrollClipLayer(3);
3136 scroll_layer->SetBounds(contents_size);
3137 scroll_layer->SetContentBounds(contents_size);
3138 scroll_layer->SetPosition(gfx::PointF());
3139 scroll_layer->AddChild(content_layer.Pass());
3140 scroll_clip_layer->AddChild(scroll_layer.Pass());
3142 scroll_clip_layer->SetHasRenderSurface(true);
3143 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
3144 host_impl_->SetViewportSize(surface_size);
3145 DrawFrame();
3147 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3148 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3149 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3150 host_impl_->ScrollEnd();
3151 EXPECT_TRUE(did_request_redraw_);
3152 EXPECT_TRUE(did_request_commit_);
3155 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
3156 gfx::Size surface_size(10, 10);
3157 gfx::Size contents_size(20, 20);
3158 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3159 root->SetBounds(surface_size);
3160 root->SetContentBounds(contents_size);
3161 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
3162 root->SetHasRenderSurface(true);
3163 host_impl_->active_tree()->SetRootLayer(root.Pass());
3164 host_impl_->SetViewportSize(surface_size);
3165 DrawFrame();
3167 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3168 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3169 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3170 host_impl_->ScrollEnd();
3171 EXPECT_TRUE(did_request_redraw_);
3172 EXPECT_TRUE(did_request_commit_);
3175 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
3176 gfx::Size surface_size(10, 10);
3177 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3178 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
3179 root->SetHasRenderSurface(true);
3180 host_impl_->active_tree()->SetRootLayer(root.Pass());
3181 host_impl_->SetViewportSize(surface_size);
3182 DrawFrame();
3184 // Scroll event is ignored because the input coordinate is outside the layer
3185 // boundaries.
3186 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3187 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
3188 EXPECT_FALSE(did_request_redraw_);
3189 EXPECT_FALSE(did_request_commit_);
3192 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
3193 gfx::Size surface_size(10, 10);
3194 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3195 root->SetHasRenderSurface(true);
3196 scoped_ptr<LayerImpl> child =
3197 CreateScrollableLayer(2, surface_size, root.get());
3198 host_impl_->SetViewportSize(surface_size);
3200 gfx::Transform matrix;
3201 matrix.RotateAboutXAxis(180.0);
3202 child->SetTransform(matrix);
3203 child->SetDoubleSided(false);
3205 root->AddChild(child.Pass());
3206 host_impl_->active_tree()->SetRootLayer(root.Pass());
3207 DrawFrame();
3209 // Scroll event is ignored because the scrollable layer is not facing the
3210 // viewer and there is nothing scrollable behind it.
3211 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3212 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3213 EXPECT_FALSE(did_request_redraw_);
3214 EXPECT_FALSE(did_request_commit_);
3217 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
3218 gfx::Size surface_size(10, 10);
3219 scoped_ptr<LayerImpl> clip_layer =
3220 LayerImpl::Create(host_impl_->active_tree(), 3);
3221 scoped_ptr<LayerImpl> content_layer =
3222 CreateScrollableLayer(1, surface_size, clip_layer.get());
3223 content_layer->SetShouldScrollOnMainThread(true);
3224 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
3226 // Note: we can use the same clip layer for both since both calls to
3227 // CreateScrollableLayer() use the same surface size.
3228 scoped_ptr<LayerImpl> scroll_layer =
3229 CreateScrollableLayer(2, surface_size, clip_layer.get());
3230 scroll_layer->AddChild(content_layer.Pass());
3231 clip_layer->AddChild(scroll_layer.Pass());
3232 clip_layer->SetHasRenderSurface(true);
3234 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
3235 host_impl_->SetViewportSize(surface_size);
3236 DrawFrame();
3238 // Scrolling fails because the content layer is asking to be scrolled on the
3239 // main thread.
3240 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
3241 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3244 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
3245 gfx::Size surface_size(20, 20);
3246 gfx::Size viewport_size(10, 10);
3247 float page_scale = 2.f;
3248 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3249 scoped_ptr<LayerImpl> root_clip =
3250 LayerImpl::Create(host_impl_->active_tree(), 2);
3251 scoped_ptr<LayerImpl> root_scrolling =
3252 CreateScrollableLayer(3, surface_size, root_clip.get());
3253 EXPECT_EQ(viewport_size, root_clip->bounds());
3254 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3255 root_clip->AddChild(root_scrolling.Pass());
3256 root->AddChild(root_clip.Pass());
3257 root->SetHasRenderSurface(true);
3258 host_impl_->active_tree()->SetRootLayer(root.Pass());
3259 // The behaviour in this test assumes the page scale is applied at a layer
3260 // above the clip layer.
3261 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3262 Layer::INVALID_ID);
3263 host_impl_->active_tree()->DidBecomeActive();
3264 host_impl_->SetViewportSize(viewport_size);
3265 DrawFrame();
3267 LayerImpl* root_scroll =
3268 host_impl_->active_tree()->InnerViewportScrollLayer();
3269 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3271 gfx::Vector2d scroll_delta(0, 10);
3272 gfx::Vector2d expected_scroll_delta = scroll_delta;
3273 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3274 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3275 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3276 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3277 host_impl_->ScrollEnd();
3279 // Set new page scale from main thread.
3280 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale,
3281 page_scale);
3283 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3284 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3286 // The scroll range should also have been updated.
3287 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3289 // The page scale delta remains constant because the impl thread did not
3290 // scale.
3291 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3294 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3295 gfx::Size surface_size(20, 20);
3296 gfx::Size viewport_size(10, 10);
3297 float page_scale = 2.f;
3298 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3299 scoped_ptr<LayerImpl> root_clip =
3300 LayerImpl::Create(host_impl_->active_tree(), 2);
3301 scoped_ptr<LayerImpl> root_scrolling =
3302 CreateScrollableLayer(3, surface_size, root_clip.get());
3303 EXPECT_EQ(viewport_size, root_clip->bounds());
3304 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3305 root_clip->AddChild(root_scrolling.Pass());
3306 root->AddChild(root_clip.Pass());
3307 root->SetHasRenderSurface(true);
3308 host_impl_->active_tree()->SetRootLayer(root.Pass());
3309 // The behaviour in this test assumes the page scale is applied at a layer
3310 // above the clip layer.
3311 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3312 Layer::INVALID_ID);
3313 host_impl_->active_tree()->DidBecomeActive();
3314 host_impl_->SetViewportSize(viewport_size);
3315 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale);
3316 DrawFrame();
3318 LayerImpl* root_scroll =
3319 host_impl_->active_tree()->InnerViewportScrollLayer();
3320 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3322 gfx::Vector2d scroll_delta(0, 10);
3323 gfx::Vector2d expected_scroll_delta = scroll_delta;
3324 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3325 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3326 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3327 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3328 host_impl_->ScrollEnd();
3330 // Set new page scale on impl thread by pinching.
3331 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3332 host_impl_->PinchGestureBegin();
3333 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3334 host_impl_->PinchGestureEnd();
3335 host_impl_->ScrollEnd();
3336 DrawOneFrame();
3338 // The scroll delta is not scaled because the main thread did not scale.
3339 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3340 ExpectContains(*scroll_info.get(), root_scroll->id(), expected_scroll_delta);
3342 // The scroll range should also have been updated.
3343 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3345 // The page scale delta should match the new scale on the impl side.
3346 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3349 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3350 gfx::Size surface_size(10, 10);
3351 float default_page_scale = 1.f;
3352 gfx::Transform default_page_scale_matrix;
3353 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3355 float new_page_scale = 2.f;
3356 gfx::Transform new_page_scale_matrix;
3357 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3359 // Create a normal scrollable root layer and another scrollable child layer.
3360 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3361 LayerImpl* root = host_impl_->active_tree()->root_layer();
3362 LayerImpl* child = scroll->children()[0];
3364 scoped_ptr<LayerImpl> scrollable_child_clip =
3365 LayerImpl::Create(host_impl_->active_tree(), 6);
3366 scoped_ptr<LayerImpl> scrollable_child =
3367 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3368 scrollable_child_clip->AddChild(scrollable_child.Pass());
3369 child->AddChild(scrollable_child_clip.Pass());
3370 LayerImpl* grand_child = child->children()[0];
3372 // Set new page scale on impl thread by pinching.
3373 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3374 host_impl_->PinchGestureBegin();
3375 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3376 host_impl_->PinchGestureEnd();
3377 host_impl_->ScrollEnd();
3378 DrawOneFrame();
3380 EXPECT_EQ(1.f, root->contents_scale_x());
3381 EXPECT_EQ(1.f, root->contents_scale_y());
3382 EXPECT_EQ(1.f, scroll->contents_scale_x());
3383 EXPECT_EQ(1.f, scroll->contents_scale_y());
3384 EXPECT_EQ(1.f, child->contents_scale_x());
3385 EXPECT_EQ(1.f, child->contents_scale_y());
3386 EXPECT_EQ(1.f, grand_child->contents_scale_x());
3387 EXPECT_EQ(1.f, grand_child->contents_scale_y());
3389 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3390 // the page scale delta on the root layer is applied hierarchically.
3391 LayerTreeHostImpl::FrameData frame;
3392 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3393 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
3394 host_impl_->DidDrawAllLayers(frame);
3396 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3397 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3398 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3399 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3400 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3401 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3402 EXPECT_EQ(new_page_scale,
3403 grand_child->draw_transform().matrix().getDouble(0, 0));
3404 EXPECT_EQ(new_page_scale,
3405 grand_child->draw_transform().matrix().getDouble(1, 1));
3408 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3409 gfx::Size surface_size(30, 30);
3410 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3411 root->SetBounds(gfx::Size(5, 5));
3412 root->SetHasRenderSurface(true);
3413 scoped_ptr<LayerImpl> root_scrolling =
3414 LayerImpl::Create(host_impl_->active_tree(), 2);
3415 root_scrolling->SetBounds(surface_size);
3416 root_scrolling->SetContentBounds(surface_size);
3417 root_scrolling->SetScrollClipLayer(root->id());
3418 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3419 LayerImpl* root_scrolling_ptr = root_scrolling.get();
3420 root->AddChild(root_scrolling.Pass());
3421 int child_scroll_layer_id = 3;
3422 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
3423 child_scroll_layer_id, surface_size, root_scrolling_ptr);
3424 LayerImpl* child = child_scrolling.get();
3425 root_scrolling_ptr->AddChild(child_scrolling.Pass());
3426 host_impl_->active_tree()->SetRootLayer(root.Pass());
3427 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3428 Layer::INVALID_ID);
3429 host_impl_->active_tree()->DidBecomeActive();
3430 host_impl_->SetViewportSize(surface_size);
3431 DrawFrame();
3433 gfx::Vector2d scroll_delta(0, 10);
3434 gfx::Vector2d expected_scroll_delta(scroll_delta);
3435 gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
3436 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3437 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3438 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3439 host_impl_->ScrollEnd();
3441 float page_scale = 2.f;
3442 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
3443 page_scale);
3445 DrawOneFrame();
3447 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3448 ExpectContains(
3449 *scroll_info.get(), child_scroll_layer_id, expected_scroll_delta);
3451 // The scroll range should not have changed.
3452 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
3454 // The page scale delta remains constant because the impl thread did not
3455 // scale.
3456 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3459 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
3460 // Scroll a child layer beyond its maximum scroll range and make sure the
3461 // parent layer is scrolled on the axis on which the child was unable to
3462 // scroll.
3463 gfx::Size surface_size(10, 10);
3464 gfx::Size content_size(20, 20);
3465 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3466 root->SetBounds(surface_size);
3467 root->SetHasRenderSurface(true);
3468 scoped_ptr<LayerImpl> grand_child =
3469 CreateScrollableLayer(3, content_size, root.get());
3471 scoped_ptr<LayerImpl> child =
3472 CreateScrollableLayer(2, content_size, root.get());
3473 LayerImpl* grand_child_layer = grand_child.get();
3474 child->AddChild(grand_child.Pass());
3476 LayerImpl* child_layer = child.get();
3477 root->AddChild(child.Pass());
3478 host_impl_->active_tree()->SetRootLayer(root.Pass());
3479 host_impl_->active_tree()->DidBecomeActive();
3480 host_impl_->SetViewportSize(surface_size);
3481 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3482 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3484 DrawFrame();
3486 gfx::Vector2d scroll_delta(-8, -7);
3487 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3488 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3489 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3490 host_impl_->ScrollEnd();
3492 scoped_ptr<ScrollAndScaleSet> scroll_info =
3493 host_impl_->ProcessScrollDeltas();
3495 // The grand child should have scrolled up to its limit.
3496 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3497 LayerImpl* grand_child = child->children()[0];
3498 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -5));
3500 // The child should have only scrolled on the other axis.
3501 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(-3, 0));
3505 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
3506 // Scroll a child layer beyond its maximum scroll range and make sure the
3507 // the scroll doesn't bubble up to the parent layer.
3508 gfx::Size surface_size(20, 20);
3509 gfx::Size viewport_size(10, 10);
3510 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3511 root->SetHasRenderSurface(true);
3512 scoped_ptr<LayerImpl> root_scrolling =
3513 CreateScrollableLayer(2, surface_size, root.get());
3514 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3516 scoped_ptr<LayerImpl> grand_child =
3517 CreateScrollableLayer(4, surface_size, root.get());
3519 scoped_ptr<LayerImpl> child =
3520 CreateScrollableLayer(3, surface_size, root.get());
3521 LayerImpl* grand_child_layer = grand_child.get();
3522 child->AddChild(grand_child.Pass());
3524 LayerImpl* child_layer = child.get();
3525 root_scrolling->AddChild(child.Pass());
3526 root->AddChild(root_scrolling.Pass());
3527 EXPECT_EQ(viewport_size, root->bounds());
3528 host_impl_->active_tree()->SetRootLayer(root.Pass());
3529 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3530 Layer::INVALID_ID);
3531 host_impl_->active_tree()->DidBecomeActive();
3532 host_impl_->SetViewportSize(viewport_size);
3534 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3535 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3537 DrawFrame();
3539 gfx::Vector2d scroll_delta(0, -10);
3540 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3541 host_impl_->ScrollBegin(gfx::Point(),
3542 InputHandler::NON_BUBBLING_GESTURE));
3543 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3544 host_impl_->ScrollEnd();
3546 scoped_ptr<ScrollAndScaleSet> scroll_info =
3547 host_impl_->ProcessScrollDeltas();
3549 // The grand child should have scrolled up to its limit.
3550 LayerImpl* child =
3551 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
3552 LayerImpl* grand_child = child->children()[0];
3553 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3555 // The child should not have scrolled.
3556 ExpectNone(*scroll_info.get(), child->id());
3558 // The next time we scroll we should only scroll the parent.
3559 scroll_delta = gfx::Vector2d(0, -3);
3560 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3561 host_impl_->ScrollBegin(gfx::Point(5, 5),
3562 InputHandler::NON_BUBBLING_GESTURE));
3563 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3564 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3565 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
3566 host_impl_->ScrollEnd();
3568 scroll_info = host_impl_->ProcessScrollDeltas();
3570 // The child should have scrolled up to its limit.
3571 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3573 // The grand child should not have scrolled.
3574 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, -2));
3576 // After scrolling the parent, another scroll on the opposite direction
3577 // should still scroll the child.
3578 scroll_delta = gfx::Vector2d(0, 7);
3579 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3580 host_impl_->ScrollBegin(gfx::Point(5, 5),
3581 InputHandler::NON_BUBBLING_GESTURE));
3582 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3583 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3584 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3585 host_impl_->ScrollEnd();
3587 scroll_info = host_impl_->ProcessScrollDeltas();
3589 // The grand child should have scrolled.
3590 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 5));
3592 // The child should not have scrolled.
3593 ExpectContains(*scroll_info.get(), child->id(), gfx::Vector2d(0, -3));
3596 // Scrolling should be adjusted from viewport space.
3597 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
3598 host_impl_->SetPageScaleOnActiveTree(2.f);
3600 scroll_delta = gfx::Vector2d(0, -2);
3601 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3602 host_impl_->ScrollBegin(gfx::Point(1, 1),
3603 InputHandler::NON_BUBBLING_GESTURE));
3604 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
3605 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3606 host_impl_->ScrollEnd();
3608 scroll_info = host_impl_->ProcessScrollDeltas();
3610 // Should have scrolled by half the amount in layer space (5 - 2/2)
3611 ExpectContains(*scroll_info.get(), grand_child->id(), gfx::Vector2d(0, 4));
3614 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
3615 // When we try to scroll a non-scrollable child layer, the scroll delta
3616 // should be applied to one of its ancestors if possible.
3617 gfx::Size surface_size(10, 10);
3618 gfx::Size content_size(20, 20);
3619 scoped_ptr<LayerImpl> root_clip =
3620 LayerImpl::Create(host_impl_->active_tree(), 3);
3621 root_clip->SetHasRenderSurface(true);
3622 scoped_ptr<LayerImpl> root =
3623 CreateScrollableLayer(1, content_size, root_clip.get());
3624 // Make 'root' the clip layer for child: since they have the same sizes the
3625 // child will have zero max_scroll_offset and scrolls will bubble.
3626 scoped_ptr<LayerImpl> child =
3627 CreateScrollableLayer(2, content_size, root.get());
3628 child->SetIsContainerForFixedPositionLayers(true);
3629 root->SetBounds(content_size);
3631 int root_scroll_id = root->id();
3632 root->AddChild(child.Pass());
3633 root_clip->AddChild(root.Pass());
3635 host_impl_->SetViewportSize(surface_size);
3636 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3637 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
3638 Layer::INVALID_ID);
3639 host_impl_->active_tree()->DidBecomeActive();
3640 DrawFrame();
3642 gfx::Vector2d scroll_delta(0, 4);
3643 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3644 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3645 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3646 host_impl_->ScrollEnd();
3648 scoped_ptr<ScrollAndScaleSet> scroll_info =
3649 host_impl_->ProcessScrollDeltas();
3651 // Only the root scroll should have scrolled.
3652 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
3653 ExpectContains(*scroll_info.get(), root_scroll_id, scroll_delta);
3657 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
3658 gfx::Size surface_size(10, 10);
3659 scoped_ptr<LayerImpl> root_clip =
3660 LayerImpl::Create(host_impl_->active_tree(), 1);
3661 scoped_ptr<LayerImpl> root_scroll =
3662 CreateScrollableLayer(2, surface_size, root_clip.get());
3663 root_scroll->SetIsContainerForFixedPositionLayers(true);
3664 root_clip->SetHasRenderSurface(true);
3665 root_clip->AddChild(root_scroll.Pass());
3666 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3667 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3668 Layer::INVALID_ID);
3669 host_impl_->active_tree()->DidBecomeActive();
3670 host_impl_->SetViewportSize(surface_size);
3672 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3673 // synchronization.
3674 DrawFrame();
3675 host_impl_->active_tree()->DetachLayerTree();
3676 scoped_ptr<LayerImpl> root_clip2 =
3677 LayerImpl::Create(host_impl_->active_tree(), 3);
3678 scoped_ptr<LayerImpl> root_scroll2 =
3679 CreateScrollableLayer(4, surface_size, root_clip2.get());
3680 root_scroll2->SetIsContainerForFixedPositionLayers(true);
3681 root_clip2->AddChild(root_scroll2.Pass());
3682 root_clip2->SetHasRenderSurface(true);
3683 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
3684 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
3685 Layer::INVALID_ID);
3686 host_impl_->active_tree()->DidBecomeActive();
3688 // Scrolling should still work even though we did not draw yet.
3689 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3690 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3693 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
3694 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3696 // Rotate the root layer 90 degrees counter-clockwise about its center.
3697 gfx::Transform rotate_transform;
3698 rotate_transform.Rotate(-90.0);
3699 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
3701 gfx::Size surface_size(50, 50);
3702 host_impl_->SetViewportSize(surface_size);
3703 DrawFrame();
3705 // Scroll to the right in screen coordinates with a gesture.
3706 gfx::Vector2d gesture_scroll_delta(10, 0);
3707 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3708 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3709 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3710 host_impl_->ScrollEnd();
3712 // The layer should have scrolled down in its local coordinates.
3713 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3714 ExpectContains(*scroll_info.get(), scroll_layer->id(),
3715 gfx::Vector2d(0, gesture_scroll_delta.x()));
3717 // Reset and scroll down with the wheel.
3718 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3719 gfx::Vector2d wheel_scroll_delta(0, 10);
3720 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3721 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3722 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3723 host_impl_->ScrollEnd();
3725 // The layer should have scrolled down in its local coordinates.
3726 scroll_info = host_impl_->ProcessScrollDeltas();
3727 ExpectContains(*scroll_info.get(),
3728 scroll_layer->id(),
3729 wheel_scroll_delta);
3732 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
3733 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3734 int child_clip_layer_id = 6;
3735 int child_layer_id = 7;
3736 float child_layer_angle = -20.f;
3738 // Create a child layer that is rotated to a non-axis-aligned angle.
3739 scoped_ptr<LayerImpl> clip_layer =
3740 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
3741 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
3742 child_layer_id, scroll_layer->content_bounds(), clip_layer.get());
3743 gfx::Transform rotate_transform;
3744 rotate_transform.Translate(-50.0, -50.0);
3745 rotate_transform.Rotate(child_layer_angle);
3746 rotate_transform.Translate(50.0, 50.0);
3747 clip_layer->SetTransform(rotate_transform);
3749 // Only allow vertical scrolling.
3750 clip_layer->SetBounds(
3751 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
3752 // The rotation depends on the layer's transform origin, and the child layer
3753 // is a different size than the clip, so make sure the clip layer's origin
3754 // lines up over the child.
3755 clip_layer->SetTransformOrigin(gfx::Point3F(
3756 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
3757 LayerImpl* child_ptr = child.get();
3758 clip_layer->AddChild(child.Pass());
3759 scroll_layer->AddChild(clip_layer.Pass());
3761 gfx::Size surface_size(50, 50);
3762 host_impl_->SetViewportSize(surface_size);
3763 DrawFrame();
3765 // Scroll down in screen coordinates with a gesture.
3766 gfx::Vector2d gesture_scroll_delta(0, 10);
3767 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3768 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
3769 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3770 host_impl_->ScrollEnd();
3772 // The child layer should have scrolled down in its local coordinates an
3773 // amount proportional to the angle between it and the input scroll delta.
3774 gfx::Vector2d expected_scroll_delta(
3775 0, gesture_scroll_delta.y() *
3776 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
3777 scoped_ptr<ScrollAndScaleSet> scroll_info =
3778 host_impl_->ProcessScrollDeltas();
3779 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3781 // The root scroll layer should not have scrolled, because the input delta
3782 // was close to the layer's axis of movement.
3783 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
3786 // Now reset and scroll the same amount horizontally.
3787 child_ptr->SetScrollDelta(gfx::Vector2dF());
3788 gfx::Vector2d gesture_scroll_delta(10, 0);
3789 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3790 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
3791 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3792 host_impl_->ScrollEnd();
3794 // The child layer should have scrolled down in its local coordinates an
3795 // amount proportional to the angle between it and the input scroll delta.
3796 gfx::Vector2d expected_scroll_delta(
3797 0, -gesture_scroll_delta.x() *
3798 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
3799 scoped_ptr<ScrollAndScaleSet> scroll_info =
3800 host_impl_->ProcessScrollDeltas();
3801 ExpectContains(*scroll_info.get(), child_layer_id, expected_scroll_delta);
3803 // The root scroll layer should have scrolled more, since the input scroll
3804 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3805 gfx::Vector2d expected_root_scroll_delta(
3806 gesture_scroll_delta.x() *
3807 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
3809 ExpectContains(*scroll_info.get(),
3810 scroll_layer->id(),
3811 expected_root_scroll_delta);
3815 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
3816 LayerImpl* scroll_layer =
3817 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3819 // Scale the layer to twice its normal size.
3820 int scale = 2;
3821 gfx::Transform scale_transform;
3822 scale_transform.Scale(scale, scale);
3823 scroll_layer->SetTransform(scale_transform);
3825 gfx::Size surface_size(50, 50);
3826 host_impl_->SetViewportSize(surface_size);
3827 DrawFrame();
3829 // Scroll down in screen coordinates with a gesture.
3830 gfx::Vector2d scroll_delta(0, 10);
3831 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3832 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3833 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3834 host_impl_->ScrollEnd();
3836 // The layer should have scrolled down in its local coordinates, but half the
3837 // amount.
3838 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3839 ExpectContains(*scroll_info.get(),
3840 scroll_layer->id(),
3841 gfx::Vector2d(0, scroll_delta.y() / scale));
3843 // Reset and scroll down with the wheel.
3844 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3845 gfx::Vector2d wheel_scroll_delta(0, 10);
3846 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3847 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3848 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3849 host_impl_->ScrollEnd();
3851 // It should apply the scale factor to the scroll delta for the wheel event.
3852 scroll_info = host_impl_->ProcessScrollDeltas();
3853 ExpectContains(*scroll_info.get(),
3854 scroll_layer->id(),
3855 wheel_scroll_delta);
3858 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
3859 int width = 332;
3860 int height = 20;
3861 int scale = 3;
3862 SetupScrollAndContentsLayers(gfx::Size(width, height));
3863 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
3864 gfx::Size(width * scale - 1, height * scale));
3865 host_impl_->SetDeviceScaleFactor(scale);
3866 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3868 LayerImpl* inner_viewport_scroll_layer =
3869 host_impl_->active_tree()->InnerViewportScrollLayer();
3870 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3871 inner_viewport_scroll_layer->MaxScrollOffset());
3874 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
3875 public:
3876 TestScrollOffsetDelegate()
3877 : page_scale_factor_(0.f),
3878 min_page_scale_factor_(-1.f),
3879 max_page_scale_factor_(-1.f) {}
3881 ~TestScrollOffsetDelegate() override {}
3883 gfx::ScrollOffset GetTotalScrollOffset() override {
3884 return getter_return_value_;
3887 bool IsExternalFlingActive() const override { return false; }
3889 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
3890 const gfx::ScrollOffset& max_scroll_offset,
3891 const gfx::SizeF& scrollable_size,
3892 float page_scale_factor,
3893 float min_page_scale_factor,
3894 float max_page_scale_factor) override {
3895 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
3896 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
3897 last_set_scroll_offset_ = total_scroll_offset;
3898 max_scroll_offset_ = max_scroll_offset;
3899 scrollable_size_ = scrollable_size;
3900 page_scale_factor_ = page_scale_factor;
3901 min_page_scale_factor_ = min_page_scale_factor;
3902 max_page_scale_factor_ = max_page_scale_factor;
3904 set_getter_return_value(last_set_scroll_offset_);
3907 gfx::ScrollOffset last_set_scroll_offset() {
3908 return last_set_scroll_offset_;
3911 void set_getter_return_value(const gfx::ScrollOffset& value) {
3912 getter_return_value_ = value;
3915 gfx::ScrollOffset max_scroll_offset() const {
3916 return max_scroll_offset_;
3919 gfx::SizeF scrollable_size() const {
3920 return scrollable_size_;
3923 float page_scale_factor() const {
3924 return page_scale_factor_;
3927 float min_page_scale_factor() const {
3928 return min_page_scale_factor_;
3931 float max_page_scale_factor() const {
3932 return max_page_scale_factor_;
3935 private:
3936 gfx::ScrollOffset last_set_scroll_offset_;
3937 gfx::ScrollOffset getter_return_value_;
3938 gfx::ScrollOffset max_scroll_offset_;
3939 gfx::SizeF scrollable_size_;
3940 float page_scale_factor_;
3941 float min_page_scale_factor_;
3942 float max_page_scale_factor_;
3945 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
3946 TestScrollOffsetDelegate scroll_delegate;
3947 host_impl_->SetViewportSize(gfx::Size(10, 20));
3948 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3949 LayerImpl* clip_layer = scroll_layer->parent()->parent();
3950 clip_layer->SetBounds(gfx::Size(10, 20));
3952 // Setting the delegate results in the current scroll offset being set.
3953 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
3954 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
3955 scroll_layer->SetScrollDelta(initial_scroll_delta);
3956 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
3957 EXPECT_EQ(initial_scroll_delta.ToString(),
3958 scroll_delegate.last_set_scroll_offset().ToString());
3960 // Setting the delegate results in the scrollable_size, max_scroll_offset,
3961 // page_scale_factor and {min|max}_page_scale_factor being set.
3962 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
3963 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
3964 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3965 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
3966 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
3968 // Updating page scale immediately updates the delegate.
3969 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
3970 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
3971 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3972 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3973 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
3974 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
3975 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3976 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3977 host_impl_->SetPageScaleOnActiveTree(2.f);
3978 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
3979 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
3980 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
3981 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
3983 // The pinch gesture doesn't put the delegate into a state where the scroll
3984 // offset is outside of the scroll range. (this is verified by DCHECKs in the
3985 // delegate).
3986 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3987 host_impl_->PinchGestureBegin();
3988 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
3989 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
3990 host_impl_->PinchGestureEnd();
3991 host_impl_->ScrollEnd();
3993 // Scrolling should be relative to the offset as returned by the delegate.
3994 gfx::Vector2dF scroll_delta(0.f, 10.f);
3995 gfx::ScrollOffset current_offset(7.f, 8.f);
3997 scroll_delegate.set_getter_return_value(current_offset);
3998 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3999 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4000 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4002 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4003 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
4004 scroll_delegate.last_set_scroll_offset());
4006 current_offset = gfx::ScrollOffset(42.f, 41.f);
4007 scroll_delegate.set_getter_return_value(current_offset);
4008 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4009 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4010 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
4011 scroll_delegate.last_set_scroll_offset());
4012 host_impl_->ScrollEnd();
4013 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
4014 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4016 // Forces a full tree synchronization and ensures that the scroll delegate
4017 // sees the correct size of the new tree.
4018 gfx::Size new_size(42, 24);
4019 host_impl_->CreatePendingTree();
4020 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
4021 host_impl_->ActivateSyncTree();
4022 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
4024 // Un-setting the delegate should propagate the delegate's current offset to
4025 // the root scrollable layer.
4026 current_offset = gfx::ScrollOffset(13.f, 12.f);
4027 scroll_delegate.set_getter_return_value(current_offset);
4028 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4029 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4031 EXPECT_EQ(current_offset.ToString(),
4032 scroll_layer->CurrentScrollOffset().ToString());
4035 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
4036 const gfx::Transform target_space_transform =
4037 layer->draw_properties().target_space_transform;
4038 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
4039 gfx::Point translated_point;
4040 target_space_transform.TransformPoint(&translated_point);
4041 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
4042 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
4045 TEST_F(LayerTreeHostImplTest,
4046 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
4047 TestScrollOffsetDelegate scroll_delegate;
4048 host_impl_->SetViewportSize(gfx::Size(10, 20));
4049 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4050 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4051 clip_layer->SetBounds(gfx::Size(10, 20));
4052 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4054 // Draw first frame to clear any pending draws and check scroll.
4055 DrawFrame();
4056 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
4057 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
4059 // Set external scroll delta on delegate and notify LayerTreeHost.
4060 gfx::ScrollOffset scroll_offset(10.f, 10.f);
4061 scroll_delegate.set_getter_return_value(scroll_offset);
4062 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4064 // Check scroll delta reflected in layer.
4065 LayerTreeHostImpl::FrameData frame;
4066 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4067 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4068 host_impl_->DidDrawAllLayers(frame);
4069 EXPECT_FALSE(frame.has_no_damage);
4070 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
4072 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4075 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
4076 InputHandlerScrollResult scroll_result;
4077 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4078 host_impl_->SetViewportSize(gfx::Size(50, 50));
4079 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4080 DrawFrame();
4081 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4083 // In-bounds scrolling does not affect overscroll.
4084 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4085 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4086 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4087 EXPECT_TRUE(scroll_result.did_scroll);
4088 EXPECT_FALSE(scroll_result.did_overscroll_root);
4089 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4090 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4092 // Overscroll events are reflected immediately.
4093 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4094 EXPECT_TRUE(scroll_result.did_scroll);
4095 EXPECT_TRUE(scroll_result.did_overscroll_root);
4096 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4097 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4098 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4099 host_impl_->accumulated_root_overscroll());
4101 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4102 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4103 EXPECT_TRUE(scroll_result.did_scroll);
4104 EXPECT_FALSE(scroll_result.did_overscroll_root);
4105 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4106 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4107 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4108 host_impl_->accumulated_root_overscroll());
4110 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4111 EXPECT_FALSE(scroll_result.did_scroll);
4112 EXPECT_TRUE(scroll_result.did_overscroll_root);
4113 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4114 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4115 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4116 host_impl_->accumulated_root_overscroll());
4118 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4119 EXPECT_TRUE(scroll_result.did_scroll);
4120 EXPECT_FALSE(scroll_result.did_overscroll_root);
4121 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4122 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4123 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4124 host_impl_->accumulated_root_overscroll());
4126 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4127 EXPECT_TRUE(scroll_result.did_scroll);
4128 EXPECT_TRUE(scroll_result.did_overscroll_root);
4129 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
4130 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
4131 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4132 host_impl_->accumulated_root_overscroll());
4134 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4135 EXPECT_TRUE(scroll_result.did_scroll);
4136 EXPECT_TRUE(scroll_result.did_overscroll_root);
4137 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4138 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
4139 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4140 host_impl_->accumulated_root_overscroll());
4142 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4143 EXPECT_TRUE(scroll_result.did_scroll);
4144 EXPECT_TRUE(scroll_result.did_overscroll_root);
4145 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4146 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4147 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4148 host_impl_->accumulated_root_overscroll());
4150 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4151 // as no scroll occurs.
4152 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4153 EXPECT_FALSE(scroll_result.did_scroll);
4154 EXPECT_TRUE(scroll_result.did_overscroll_root);
4155 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4156 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
4157 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4158 host_impl_->accumulated_root_overscroll());
4160 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4161 EXPECT_FALSE(scroll_result.did_scroll);
4162 EXPECT_TRUE(scroll_result.did_overscroll_root);
4163 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4164 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
4165 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4166 host_impl_->accumulated_root_overscroll());
4168 // Overscroll resets on valid scroll.
4169 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4170 EXPECT_TRUE(scroll_result.did_scroll);
4171 EXPECT_FALSE(scroll_result.did_overscroll_root);
4172 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4173 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4174 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4175 host_impl_->accumulated_root_overscroll());
4177 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4178 EXPECT_TRUE(scroll_result.did_scroll);
4179 EXPECT_TRUE(scroll_result.did_overscroll_root);
4180 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4181 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4182 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4183 host_impl_->accumulated_root_overscroll());
4185 host_impl_->ScrollEnd();
4189 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
4190 // Scroll child layers beyond their maximum scroll range and make sure root
4191 // overscroll does not accumulate.
4192 gfx::Size surface_size(10, 10);
4193 scoped_ptr<LayerImpl> root_clip =
4194 LayerImpl::Create(host_impl_->active_tree(), 4);
4195 root_clip->SetHasRenderSurface(true);
4197 scoped_ptr<LayerImpl> root =
4198 CreateScrollableLayer(1, surface_size, root_clip.get());
4200 scoped_ptr<LayerImpl> grand_child =
4201 CreateScrollableLayer(3, surface_size, root_clip.get());
4203 scoped_ptr<LayerImpl> child =
4204 CreateScrollableLayer(2, surface_size, root_clip.get());
4205 LayerImpl* grand_child_layer = grand_child.get();
4206 child->AddChild(grand_child.Pass());
4208 LayerImpl* child_layer = child.get();
4209 root->AddChild(child.Pass());
4210 root_clip->AddChild(root.Pass());
4211 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4212 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4213 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4214 host_impl_->active_tree()->DidBecomeActive();
4215 host_impl_->SetViewportSize(surface_size);
4216 DrawFrame();
4218 gfx::Vector2d scroll_delta(0, -10);
4219 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4220 host_impl_->ScrollBegin(gfx::Point(),
4221 InputHandler::NON_BUBBLING_GESTURE));
4222 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4223 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4224 host_impl_->ScrollEnd();
4226 // The next time we scroll we should only scroll the parent, but overscroll
4227 // should still not reach the root layer.
4228 scroll_delta = gfx::Vector2d(0, -30);
4229 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4230 host_impl_->ScrollBegin(gfx::Point(5, 5),
4231 InputHandler::NON_BUBBLING_GESTURE));
4232 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4233 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4234 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4235 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
4236 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4237 host_impl_->ScrollEnd();
4239 // After scrolling the parent, another scroll on the opposite direction
4240 // should scroll the child.
4241 scroll_delta = gfx::Vector2d(0, 70);
4242 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4243 host_impl_->ScrollBegin(gfx::Point(5, 5),
4244 InputHandler::NON_BUBBLING_GESTURE));
4245 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4246 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4247 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4248 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4249 host_impl_->ScrollEnd();
4253 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
4254 // When we try to scroll a non-scrollable child layer, the scroll delta
4255 // should be applied to one of its ancestors if possible. Overscroll should
4256 // be reflected only when it has bubbled up to the root scrolling layer.
4257 gfx::Size surface_size(10, 10);
4258 gfx::Size content_size(20, 20);
4259 scoped_ptr<LayerImpl> root_clip =
4260 LayerImpl::Create(host_impl_->active_tree(), 3);
4261 root_clip->SetHasRenderSurface(true);
4263 scoped_ptr<LayerImpl> root =
4264 CreateScrollableLayer(1, content_size, root_clip.get());
4265 root->SetIsContainerForFixedPositionLayers(true);
4266 scoped_ptr<LayerImpl> child =
4267 CreateScrollableLayer(2, content_size, root_clip.get());
4269 child->SetScrollClipLayer(Layer::INVALID_ID);
4270 root->AddChild(child.Pass());
4271 root_clip->AddChild(root.Pass());
4273 host_impl_->SetViewportSize(surface_size);
4274 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4275 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4276 Layer::INVALID_ID);
4277 host_impl_->active_tree()->DidBecomeActive();
4278 DrawFrame();
4280 gfx::Vector2d scroll_delta(0, 8);
4281 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4282 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4283 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4284 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4285 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4286 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4287 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4288 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4289 host_impl_->ScrollEnd();
4293 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4294 LayerTreeSettings settings;
4295 CreateHostImpl(settings, CreateOutputSurface());
4297 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4298 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4299 clip_layer->SetBounds(gfx::Size(50, 50));
4300 host_impl_->SetViewportSize(gfx::Size(50, 50));
4301 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4302 DrawFrame();
4303 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4305 // Even though the layer can't scroll the overscroll still happens.
4306 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4307 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4308 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4309 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4312 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
4313 gfx::Size surface_size(980, 1439);
4314 gfx::Size content_size(980, 1438);
4315 float device_scale_factor = 1.5f;
4316 scoped_ptr<LayerImpl> root_clip =
4317 LayerImpl::Create(host_impl_->active_tree(), 3);
4318 root_clip->SetHasRenderSurface(true);
4320 scoped_ptr<LayerImpl> root =
4321 CreateScrollableLayer(1, content_size, root_clip.get());
4322 root->SetIsContainerForFixedPositionLayers(true);
4323 scoped_ptr<LayerImpl> child =
4324 CreateScrollableLayer(2, content_size, root_clip.get());
4325 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4326 host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f,
4327 5.f);
4328 host_impl_->SetPageScaleOnActiveTree(0.326531f);
4329 child->SetScrollClipLayer(Layer::INVALID_ID);
4330 root->AddChild(child.Pass());
4331 root_clip->AddChild(root.Pass());
4333 host_impl_->SetViewportSize(surface_size);
4334 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4335 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4336 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4337 Layer::INVALID_ID);
4338 host_impl_->active_tree()->DidBecomeActive();
4339 DrawFrame();
4341 // Horizontal & Vertical GlowEffect should not be applied when
4342 // content size is less then view port size. For Example Horizontal &
4343 // vertical GlowEffect should not be applied in about:blank page.
4344 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4345 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4346 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4347 EXPECT_EQ(gfx::Vector2dF().ToString(),
4348 host_impl_->accumulated_root_overscroll().ToString());
4350 host_impl_->ScrollEnd();
4354 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4355 gfx::Size surface_size(100, 100);
4356 gfx::Size content_size(200, 200);
4357 scoped_ptr<LayerImpl> root_clip =
4358 LayerImpl::Create(host_impl_->active_tree(), 3);
4359 root_clip->SetHasRenderSurface(true);
4361 scoped_ptr<LayerImpl> root =
4362 CreateScrollableLayer(1, content_size, root_clip.get());
4363 root->SetIsContainerForFixedPositionLayers(true);
4364 scoped_ptr<LayerImpl> child =
4365 CreateScrollableLayer(2, content_size, root_clip.get());
4367 child->SetScrollClipLayer(Layer::INVALID_ID);
4368 root->AddChild(child.Pass());
4369 root_clip->AddChild(root.Pass());
4371 host_impl_->SetViewportSize(surface_size);
4372 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4373 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4374 Layer::INVALID_ID);
4375 host_impl_->active_tree()->DidBecomeActive();
4376 DrawFrame();
4378 // Edge glow effect should be applicable only upon reaching Edges
4379 // of the content. unnecessary glow effect calls shouldn't be
4380 // called while scrolling up without reaching the edge of the content.
4381 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4382 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4383 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4384 EXPECT_EQ(gfx::Vector2dF().ToString(),
4385 host_impl_->accumulated_root_overscroll().ToString());
4386 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4387 EXPECT_EQ(gfx::Vector2dF().ToString(),
4388 host_impl_->accumulated_root_overscroll().ToString());
4389 host_impl_->ScrollEnd();
4390 // unusedrootDelta should be subtracted from applied delta so that
4391 // unwanted glow effect calls are not called.
4392 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4393 host_impl_->ScrollBegin(gfx::Point(0, 0),
4394 InputHandler::NON_BUBBLING_GESTURE));
4395 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
4396 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4397 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4398 host_impl_->accumulated_root_overscroll().ToString());
4400 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4401 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4402 host_impl_->accumulated_root_overscroll().ToString());
4403 host_impl_->ScrollEnd();
4404 // TestCase to check kEpsilon, which prevents minute values to trigger
4405 // gloweffect without reaching edge.
4406 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4407 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4408 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4409 EXPECT_EQ(gfx::Vector2dF().ToString(),
4410 host_impl_->accumulated_root_overscroll().ToString());
4411 host_impl_->ScrollEnd();
4415 class BlendStateCheckLayer : public LayerImpl {
4416 public:
4417 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4418 int id,
4419 ResourceProvider* resource_provider) {
4420 return make_scoped_ptr(
4421 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4424 void AppendQuads(RenderPass* render_pass,
4425 AppendQuadsData* append_quads_data) override {
4426 quads_appended_ = true;
4428 gfx::Rect opaque_rect;
4429 if (contents_opaque())
4430 opaque_rect = quad_rect_;
4431 else
4432 opaque_rect = opaque_content_rect_;
4433 gfx::Rect visible_quad_rect = quad_rect_;
4435 SharedQuadState* shared_quad_state =
4436 render_pass->CreateAndAppendSharedQuadState();
4437 PopulateSharedQuadState(shared_quad_state);
4439 TileDrawQuad* test_blending_draw_quad =
4440 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4441 test_blending_draw_quad->SetNew(shared_quad_state,
4442 quad_rect_,
4443 opaque_rect,
4444 visible_quad_rect,
4445 resource_id_,
4446 gfx::RectF(0.f, 0.f, 1.f, 1.f),
4447 gfx::Size(1, 1),
4448 false,
4449 false);
4450 test_blending_draw_quad->visible_rect = quad_visible_rect_;
4451 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
4452 EXPECT_EQ(has_render_surface_, !!render_surface());
4455 void SetExpectation(bool blend, bool has_render_surface) {
4456 blend_ = blend;
4457 has_render_surface_ = has_render_surface;
4458 quads_appended_ = false;
4461 bool quads_appended() const { return quads_appended_; }
4463 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
4464 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
4465 void SetOpaqueContentRect(const gfx::Rect& rect) {
4466 opaque_content_rect_ = rect;
4469 private:
4470 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
4471 int id,
4472 ResourceProvider* resource_provider)
4473 : LayerImpl(tree_impl, id),
4474 blend_(false),
4475 has_render_surface_(false),
4476 quads_appended_(false),
4477 quad_rect_(5, 5, 5, 5),
4478 quad_visible_rect_(5, 5, 5, 5),
4479 resource_id_(resource_provider->CreateResource(
4480 gfx::Size(1, 1),
4481 GL_CLAMP_TO_EDGE,
4482 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
4483 RGBA_8888)) {
4484 resource_provider->AllocateForTesting(resource_id_);
4485 SetBounds(gfx::Size(10, 10));
4486 SetContentBounds(gfx::Size(10, 10));
4487 SetDrawsContent(true);
4490 bool blend_;
4491 bool has_render_surface_;
4492 bool quads_appended_;
4493 gfx::Rect quad_rect_;
4494 gfx::Rect opaque_content_rect_;
4495 gfx::Rect quad_visible_rect_;
4496 ResourceProvider::ResourceId resource_id_;
4499 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
4501 scoped_ptr<LayerImpl> root =
4502 LayerImpl::Create(host_impl_->active_tree(), 1);
4503 root->SetBounds(gfx::Size(10, 10));
4504 root->SetContentBounds(root->bounds());
4505 root->SetDrawsContent(false);
4506 root->SetHasRenderSurface(true);
4507 host_impl_->active_tree()->SetRootLayer(root.Pass());
4509 LayerImpl* root = host_impl_->active_tree()->root_layer();
4511 root->AddChild(
4512 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4514 host_impl_->resource_provider()));
4515 BlendStateCheckLayer* layer1 =
4516 static_cast<BlendStateCheckLayer*>(root->children()[0]);
4517 layer1->SetPosition(gfx::PointF(2.f, 2.f));
4519 LayerTreeHostImpl::FrameData frame;
4521 // Opaque layer, drawn without blending.
4522 layer1->SetContentsOpaque(true);
4523 layer1->SetExpectation(false, false);
4524 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4525 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4526 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4527 EXPECT_TRUE(layer1->quads_appended());
4528 host_impl_->DidDrawAllLayers(frame);
4530 // Layer with translucent content and painting, so drawn with blending.
4531 layer1->SetContentsOpaque(false);
4532 layer1->SetExpectation(true, false);
4533 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4534 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4535 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4536 EXPECT_TRUE(layer1->quads_appended());
4537 host_impl_->DidDrawAllLayers(frame);
4539 // Layer with translucent opacity, drawn with blending.
4540 layer1->SetContentsOpaque(true);
4541 layer1->SetOpacity(0.5f);
4542 layer1->SetExpectation(true, false);
4543 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4544 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4545 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4546 EXPECT_TRUE(layer1->quads_appended());
4547 host_impl_->DidDrawAllLayers(frame);
4549 // Layer with translucent opacity and painting, drawn with blending.
4550 layer1->SetContentsOpaque(true);
4551 layer1->SetOpacity(0.5f);
4552 layer1->SetExpectation(true, false);
4553 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4554 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4555 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4556 EXPECT_TRUE(layer1->quads_appended());
4557 host_impl_->DidDrawAllLayers(frame);
4559 layer1->AddChild(
4560 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4562 host_impl_->resource_provider()));
4563 BlendStateCheckLayer* layer2 =
4564 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
4565 layer2->SetPosition(gfx::PointF(4.f, 4.f));
4567 // 2 opaque layers, drawn without blending.
4568 layer1->SetContentsOpaque(true);
4569 layer1->SetOpacity(1.f);
4570 layer1->SetExpectation(false, false);
4571 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4572 layer2->SetContentsOpaque(true);
4573 layer2->SetOpacity(1.f);
4574 layer2->SetExpectation(false, false);
4575 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4576 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4577 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4578 EXPECT_TRUE(layer1->quads_appended());
4579 EXPECT_TRUE(layer2->quads_appended());
4580 host_impl_->DidDrawAllLayers(frame);
4582 // Parent layer with translucent content, drawn with blending.
4583 // Child layer with opaque content, drawn without blending.
4584 layer1->SetContentsOpaque(false);
4585 layer1->SetExpectation(true, false);
4586 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4587 layer2->SetExpectation(false, false);
4588 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4589 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4590 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4591 EXPECT_TRUE(layer1->quads_appended());
4592 EXPECT_TRUE(layer2->quads_appended());
4593 host_impl_->DidDrawAllLayers(frame);
4595 // Parent layer with translucent content but opaque painting, drawn without
4596 // blending.
4597 // Child layer with opaque content, drawn without blending.
4598 layer1->SetContentsOpaque(true);
4599 layer1->SetExpectation(false, false);
4600 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4601 layer2->SetExpectation(false, false);
4602 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4603 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4604 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4605 EXPECT_TRUE(layer1->quads_appended());
4606 EXPECT_TRUE(layer2->quads_appended());
4607 host_impl_->DidDrawAllLayers(frame);
4609 // Parent layer with translucent opacity and opaque content. Since it has a
4610 // drawing child, it's drawn to a render surface which carries the opacity,
4611 // so it's itself drawn without blending.
4612 // Child layer with opaque content, drawn without blending (parent surface
4613 // carries the inherited opacity).
4614 layer1->SetContentsOpaque(true);
4615 layer1->SetOpacity(0.5f);
4616 layer1->SetHasRenderSurface(true);
4617 layer1->SetExpectation(false, true);
4618 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4619 layer2->SetExpectation(false, false);
4620 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4621 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4622 host_impl_->active_tree()->root_layer());
4623 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4624 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4625 EXPECT_TRUE(layer1->quads_appended());
4626 EXPECT_TRUE(layer2->quads_appended());
4627 host_impl_->DidDrawAllLayers(frame);
4628 layer1->SetHasRenderSurface(false);
4630 // Draw again, but with child non-opaque, to make sure
4631 // layer1 not culled.
4632 layer1->SetContentsOpaque(true);
4633 layer1->SetOpacity(1.f);
4634 layer1->SetExpectation(false, false);
4635 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4636 layer2->SetContentsOpaque(true);
4637 layer2->SetOpacity(0.5f);
4638 layer2->SetExpectation(true, false);
4639 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4640 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4641 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4642 EXPECT_TRUE(layer1->quads_appended());
4643 EXPECT_TRUE(layer2->quads_appended());
4644 host_impl_->DidDrawAllLayers(frame);
4646 // A second way of making the child non-opaque.
4647 layer1->SetContentsOpaque(true);
4648 layer1->SetOpacity(1.f);
4649 layer1->SetExpectation(false, false);
4650 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4651 layer2->SetContentsOpaque(false);
4652 layer2->SetOpacity(1.f);
4653 layer2->SetExpectation(true, false);
4654 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4655 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4656 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4657 EXPECT_TRUE(layer1->quads_appended());
4658 EXPECT_TRUE(layer2->quads_appended());
4659 host_impl_->DidDrawAllLayers(frame);
4661 // And when the layer says its not opaque but is painted opaque, it is not
4662 // blended.
4663 layer1->SetContentsOpaque(true);
4664 layer1->SetOpacity(1.f);
4665 layer1->SetExpectation(false, false);
4666 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4667 layer2->SetContentsOpaque(true);
4668 layer2->SetOpacity(1.f);
4669 layer2->SetExpectation(false, false);
4670 layer2->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4671 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4672 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4673 EXPECT_TRUE(layer1->quads_appended());
4674 EXPECT_TRUE(layer2->quads_appended());
4675 host_impl_->DidDrawAllLayers(frame);
4677 // Layer with partially opaque contents, drawn with blending.
4678 layer1->SetContentsOpaque(false);
4679 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4680 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4681 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4682 layer1->SetExpectation(true, false);
4683 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4684 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4685 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4686 EXPECT_TRUE(layer1->quads_appended());
4687 host_impl_->DidDrawAllLayers(frame);
4689 // Layer with partially opaque contents partially culled, drawn with blending.
4690 layer1->SetContentsOpaque(false);
4691 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4692 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4693 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4694 layer1->SetExpectation(true, false);
4695 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4696 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4697 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4698 EXPECT_TRUE(layer1->quads_appended());
4699 host_impl_->DidDrawAllLayers(frame);
4701 // Layer with partially opaque contents culled, drawn with blending.
4702 layer1->SetContentsOpaque(false);
4703 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4704 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4705 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4706 layer1->SetExpectation(true, false);
4707 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4708 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4709 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4710 EXPECT_TRUE(layer1->quads_appended());
4711 host_impl_->DidDrawAllLayers(frame);
4713 // Layer with partially opaque contents and translucent contents culled, drawn
4714 // without blending.
4715 layer1->SetContentsOpaque(false);
4716 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4717 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4718 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4719 layer1->SetExpectation(false, false);
4720 layer1->SetUpdateRect(gfx::Rect(layer1->content_bounds()));
4721 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4722 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
4723 EXPECT_TRUE(layer1->quads_appended());
4724 host_impl_->DidDrawAllLayers(frame);
4727 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
4728 protected:
4729 LayerTreeHostImplViewportCoveredTest() :
4730 gutter_quad_material_(DrawQuad::SOLID_COLOR),
4731 child_(NULL),
4732 did_activate_pending_tree_(false) {}
4734 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
4735 if (always_draw) {
4736 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4738 return FakeOutputSurface::Create3d();
4741 void SetupActiveTreeLayers() {
4742 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
4743 host_impl_->active_tree()->SetRootLayer(
4744 LayerImpl::Create(host_impl_->active_tree(), 1));
4745 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
4746 host_impl_->active_tree()->root_layer()->AddChild(
4747 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4749 host_impl_->resource_provider()));
4750 child_ = static_cast<BlendStateCheckLayer*>(
4751 host_impl_->active_tree()->root_layer()->children()[0]);
4752 child_->SetExpectation(false, false);
4753 child_->SetContentsOpaque(true);
4756 // Expect no gutter rects.
4757 void TestLayerCoversFullViewport() {
4758 gfx::Rect layer_rect(viewport_size_);
4759 child_->SetPosition(layer_rect.origin());
4760 child_->SetBounds(layer_rect.size());
4761 child_->SetContentBounds(layer_rect.size());
4762 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4763 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4765 LayerTreeHostImpl::FrameData frame;
4766 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4767 ASSERT_EQ(1u, frame.render_passes.size());
4769 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4770 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4771 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4773 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4774 host_impl_->DidDrawAllLayers(frame);
4777 // Expect fullscreen gutter rect.
4778 void TestEmptyLayer() {
4779 gfx::Rect layer_rect(0, 0, 0, 0);
4780 child_->SetPosition(layer_rect.origin());
4781 child_->SetBounds(layer_rect.size());
4782 child_->SetContentBounds(layer_rect.size());
4783 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4784 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4786 LayerTreeHostImpl::FrameData frame;
4787 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4788 ASSERT_EQ(1u, frame.render_passes.size());
4790 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
4791 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4792 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4794 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4795 host_impl_->DidDrawAllLayers(frame);
4798 // Expect four surrounding gutter rects.
4799 void TestLayerInMiddleOfViewport() {
4800 gfx::Rect layer_rect(500, 500, 200, 200);
4801 child_->SetPosition(layer_rect.origin());
4802 child_->SetBounds(layer_rect.size());
4803 child_->SetContentBounds(layer_rect.size());
4804 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4805 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4807 LayerTreeHostImpl::FrameData frame;
4808 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4809 ASSERT_EQ(1u, frame.render_passes.size());
4811 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
4812 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
4813 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4815 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
4816 host_impl_->DidDrawAllLayers(frame);
4819 // Expect no gutter rects.
4820 void TestLayerIsLargerThanViewport() {
4821 gfx::Rect layer_rect(viewport_size_.width() + 10,
4822 viewport_size_.height() + 10);
4823 child_->SetPosition(layer_rect.origin());
4824 child_->SetBounds(layer_rect.size());
4825 child_->SetContentBounds(layer_rect.size());
4826 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
4827 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
4829 LayerTreeHostImpl::FrameData frame;
4830 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4831 ASSERT_EQ(1u, frame.render_passes.size());
4833 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
4834 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
4835 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
4837 host_impl_->DidDrawAllLayers(frame);
4840 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
4842 void set_gutter_quad_material(DrawQuad::Material material) {
4843 gutter_quad_material_ = material;
4845 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
4846 gutter_texture_size_ = gutter_texture_size;
4849 protected:
4850 size_t CountGutterQuads(const QuadList& quad_list) {
4851 size_t num_gutter_quads = 0;
4852 for (const auto& quad : quad_list) {
4853 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
4855 return num_gutter_quads;
4858 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
4859 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4860 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
4863 // Make sure that the texture coordinates match their expectations.
4864 void ValidateTextureDrawQuads(const QuadList& quad_list) {
4865 for (const auto& quad : quad_list) {
4866 if (quad->material != DrawQuad::TEXTURE_CONTENT)
4867 continue;
4868 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
4869 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
4870 gutter_texture_size_, host_impl_->device_scale_factor());
4871 EXPECT_EQ(texture_quad->uv_top_left.x(),
4872 texture_quad->rect.x() / gutter_texture_size_pixels.width());
4873 EXPECT_EQ(texture_quad->uv_top_left.y(),
4874 texture_quad->rect.y() / gutter_texture_size_pixels.height());
4875 EXPECT_EQ(
4876 texture_quad->uv_bottom_right.x(),
4877 texture_quad->rect.right() / gutter_texture_size_pixels.width());
4878 EXPECT_EQ(
4879 texture_quad->uv_bottom_right.y(),
4880 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
4884 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
4885 return gfx::ToRoundedSize(
4886 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
4889 DrawQuad::Material gutter_quad_material_;
4890 gfx::Size gutter_texture_size_;
4891 gfx::Size viewport_size_;
4892 BlendStateCheckLayer* child_;
4893 bool did_activate_pending_tree_;
4896 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
4897 viewport_size_ = gfx::Size(1000, 1000);
4899 bool always_draw = false;
4900 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4902 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4903 SetupActiveTreeLayers();
4904 TestLayerCoversFullViewport();
4905 TestEmptyLayer();
4906 TestLayerInMiddleOfViewport();
4907 TestLayerIsLargerThanViewport();
4910 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
4911 viewport_size_ = gfx::Size(1000, 1000);
4913 bool always_draw = false;
4914 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4916 host_impl_->SetDeviceScaleFactor(2.f);
4917 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4918 SetupActiveTreeLayers();
4919 TestLayerCoversFullViewport();
4920 TestEmptyLayer();
4921 TestLayerInMiddleOfViewport();
4922 TestLayerIsLargerThanViewport();
4925 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
4926 viewport_size_ = gfx::Size(1000, 1000);
4928 bool always_draw = true;
4929 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4931 // Pending tree to force active_tree size invalid. Not used otherwise.
4932 host_impl_->CreatePendingTree();
4933 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4934 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4936 SetupActiveTreeLayers();
4937 TestEmptyLayer();
4938 TestLayerInMiddleOfViewport();
4939 TestLayerIsLargerThanViewport();
4942 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
4943 viewport_size_ = gfx::Size(1000, 1000);
4945 bool always_draw = true;
4946 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
4948 // Set larger viewport and activate it to active tree.
4949 host_impl_->CreatePendingTree();
4950 gfx::Size larger_viewport(viewport_size_.width() + 100,
4951 viewport_size_.height() + 100);
4952 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
4953 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4954 host_impl_->ActivateSyncTree();
4955 EXPECT_TRUE(did_activate_pending_tree_);
4956 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
4958 // Shrink pending tree viewport without activating.
4959 host_impl_->CreatePendingTree();
4960 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
4961 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
4963 SetupActiveTreeLayers();
4964 TestEmptyLayer();
4965 TestLayerInMiddleOfViewport();
4966 TestLayerIsLargerThanViewport();
4969 class FakeDrawableLayerImpl: public LayerImpl {
4970 public:
4971 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
4972 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
4974 protected:
4975 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
4976 : LayerImpl(tree_impl, id) {}
4979 // Only reshape when we know we are going to draw. Otherwise, the reshape
4980 // can leave the window at the wrong size if we never draw and the proper
4981 // viewport size is never set.
4982 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
4983 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
4984 scoped_ptr<OutputSurface> output_surface(
4985 FakeOutputSurface::Create3d(provider));
4986 CreateHostImpl(DefaultSettings(), output_surface.Pass());
4988 scoped_ptr<LayerImpl> root =
4989 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
4990 root->SetBounds(gfx::Size(10, 10));
4991 root->SetContentBounds(gfx::Size(10, 10));
4992 root->SetDrawsContent(true);
4993 root->SetHasRenderSurface(true);
4994 host_impl_->active_tree()->SetRootLayer(root.Pass());
4995 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
4996 provider->TestContext3d()->clear_reshape_called();
4998 LayerTreeHostImpl::FrameData frame;
4999 host_impl_->SetViewportSize(gfx::Size(10, 10));
5000 host_impl_->SetDeviceScaleFactor(1.f);
5001 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5002 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5003 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5004 EXPECT_EQ(provider->TestContext3d()->width(), 10);
5005 EXPECT_EQ(provider->TestContext3d()->height(), 10);
5006 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5007 host_impl_->DidDrawAllLayers(frame);
5008 provider->TestContext3d()->clear_reshape_called();
5010 host_impl_->SetViewportSize(gfx::Size(20, 30));
5011 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5012 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5013 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5014 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5015 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5016 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5017 host_impl_->DidDrawAllLayers(frame);
5018 provider->TestContext3d()->clear_reshape_called();
5020 host_impl_->SetDeviceScaleFactor(2.f);
5021 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5022 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5023 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5024 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5025 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5026 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
5027 host_impl_->DidDrawAllLayers(frame);
5028 provider->TestContext3d()->clear_reshape_called();
5031 // Make sure damage tracking propagates all the way to the graphics context,
5032 // where it should request to swap only the sub-buffer that is damaged.
5033 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
5034 scoped_refptr<TestContextProvider> context_provider(
5035 TestContextProvider::Create());
5036 context_provider->BindToCurrentThread();
5037 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
5039 scoped_ptr<FakeOutputSurface> output_surface(
5040 FakeOutputSurface::Create3d(context_provider));
5041 FakeOutputSurface* fake_output_surface = output_surface.get();
5043 // This test creates its own LayerTreeHostImpl, so
5044 // that we can force partial swap enabled.
5045 LayerTreeSettings settings;
5046 settings.renderer_settings.partial_swap_enabled = true;
5047 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
5048 LayerTreeHostImpl::Create(
5049 settings, this, &proxy_, &stats_instrumentation_,
5050 shared_bitmap_manager_.get(), NULL, task_graph_runner_.get(), 0);
5051 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
5052 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
5054 scoped_ptr<LayerImpl> root =
5055 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
5056 root->SetHasRenderSurface(true);
5057 scoped_ptr<LayerImpl> child =
5058 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
5059 child->SetPosition(gfx::PointF(12.f, 13.f));
5060 child->SetBounds(gfx::Size(14, 15));
5061 child->SetContentBounds(gfx::Size(14, 15));
5062 child->SetDrawsContent(true);
5063 root->SetBounds(gfx::Size(500, 500));
5064 root->SetContentBounds(gfx::Size(500, 500));
5065 root->SetDrawsContent(true);
5066 root->AddChild(child.Pass());
5067 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
5069 LayerTreeHostImpl::FrameData frame;
5071 // First frame, the entire screen should get swapped.
5072 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5073 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5074 layer_tree_host_impl->DidDrawAllLayers(frame);
5075 layer_tree_host_impl->SwapBuffers(frame);
5076 gfx::Rect expected_swap_rect(0, 0, 500, 500);
5077 EXPECT_EQ(expected_swap_rect.ToString(),
5078 fake_output_surface->last_swap_rect().ToString());
5080 // Second frame, only the damaged area should get swapped. Damage should be
5081 // the union of old and new child rects.
5082 // expected damage rect: gfx::Rect(26, 28);
5083 // expected swap rect: vertically flipped, with origin at bottom left corner.
5084 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
5085 gfx::PointF());
5086 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5087 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5088 host_impl_->DidDrawAllLayers(frame);
5089 layer_tree_host_impl->SwapBuffers(frame);
5091 // Make sure that partial swap is constrained to the viewport dimensions
5092 // expected damage rect: gfx::Rect(500, 500);
5093 // expected swap rect: flipped damage rect, but also clamped to viewport
5094 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
5095 EXPECT_EQ(expected_swap_rect.ToString(),
5096 fake_output_surface->last_swap_rect().ToString());
5098 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
5099 // This will damage everything.
5100 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
5101 SK_ColorBLACK);
5102 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5103 layer_tree_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5104 host_impl_->DidDrawAllLayers(frame);
5105 layer_tree_host_impl->SwapBuffers(frame);
5107 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
5108 EXPECT_EQ(expected_swap_rect.ToString(),
5109 fake_output_surface->last_swap_rect().ToString());
5112 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
5113 scoped_ptr<LayerImpl> root =
5114 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5115 scoped_ptr<LayerImpl> child =
5116 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
5117 child->SetBounds(gfx::Size(10, 10));
5118 child->SetContentBounds(gfx::Size(10, 10));
5119 child->SetDrawsContent(true);
5120 root->SetBounds(gfx::Size(10, 10));
5121 root->SetContentBounds(gfx::Size(10, 10));
5122 root->SetDrawsContent(true);
5123 root->SetHasRenderSurface(true);
5124 root->AddChild(child.Pass());
5126 host_impl_->active_tree()->SetRootLayer(root.Pass());
5128 LayerTreeHostImpl::FrameData frame;
5130 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5131 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
5132 EXPECT_EQ(1u, frame.render_passes.size());
5133 host_impl_->DidDrawAllLayers(frame);
5136 class FakeLayerWithQuads : public LayerImpl {
5137 public:
5138 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5139 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
5142 void AppendQuads(RenderPass* render_pass,
5143 AppendQuadsData* append_quads_data) override {
5144 SharedQuadState* shared_quad_state =
5145 render_pass->CreateAndAppendSharedQuadState();
5146 PopulateSharedQuadState(shared_quad_state);
5148 SkColor gray = SkColorSetRGB(100, 100, 100);
5149 gfx::Rect quad_rect(content_bounds());
5150 gfx::Rect visible_quad_rect(quad_rect);
5151 SolidColorDrawQuad* my_quad =
5152 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5153 my_quad->SetNew(
5154 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
5157 private:
5158 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
5159 : LayerImpl(tree_impl, id) {}
5162 class MockContext : public TestWebGraphicsContext3D {
5163 public:
5164 MOCK_METHOD1(useProgram, void(GLuint program));
5165 MOCK_METHOD5(uniform4f, void(GLint location,
5166 GLfloat x,
5167 GLfloat y,
5168 GLfloat z,
5169 GLfloat w));
5170 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
5171 GLsizei count,
5172 GLboolean transpose,
5173 const GLfloat* value));
5174 MOCK_METHOD4(drawElements, void(GLenum mode,
5175 GLsizei count,
5176 GLenum type,
5177 GLintptr offset));
5178 MOCK_METHOD1(enable, void(GLenum cap));
5179 MOCK_METHOD1(disable, void(GLenum cap));
5180 MOCK_METHOD4(scissor, void(GLint x,
5181 GLint y,
5182 GLsizei width,
5183 GLsizei height));
5186 class MockContextHarness {
5187 private:
5188 MockContext* context_;
5190 public:
5191 explicit MockContextHarness(MockContext* context)
5192 : context_(context) {
5193 context_->set_have_post_sub_buffer(true);
5195 // Catch "uninteresting" calls
5196 EXPECT_CALL(*context_, useProgram(_))
5197 .Times(0);
5199 EXPECT_CALL(*context_, drawElements(_, _, _, _))
5200 .Times(0);
5202 // These are not asserted
5203 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
5204 .WillRepeatedly(Return());
5206 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
5207 .WillRepeatedly(Return());
5209 // Any un-sanctioned calls to enable() are OK
5210 EXPECT_CALL(*context_, enable(_))
5211 .WillRepeatedly(Return());
5213 // Any un-sanctioned calls to disable() are OK
5214 EXPECT_CALL(*context_, disable(_))
5215 .WillRepeatedly(Return());
5218 void MustDrawSolidQuad() {
5219 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5220 .WillOnce(Return())
5221 .RetiresOnSaturation();
5223 EXPECT_CALL(*context_, useProgram(_))
5224 .WillOnce(Return())
5225 .RetiresOnSaturation();
5228 void MustSetScissor(int x, int y, int width, int height) {
5229 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5230 .WillRepeatedly(Return());
5232 EXPECT_CALL(*context_, scissor(x, y, width, height))
5233 .Times(AtLeast(1))
5234 .WillRepeatedly(Return());
5237 void MustSetNoScissor() {
5238 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5239 .WillRepeatedly(Return());
5241 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5242 .Times(0);
5244 EXPECT_CALL(*context_, scissor(_, _, _, _))
5245 .Times(0);
5249 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5250 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5251 MockContext* mock_context = mock_context_owned.get();
5252 MockContextHarness harness(mock_context);
5254 // Run test case
5255 LayerTreeSettings settings = DefaultSettings();
5256 settings.renderer_settings.partial_swap_enabled = false;
5257 CreateHostImpl(settings,
5258 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5259 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5261 // Without partial swap, and no clipping, no scissor is set.
5262 harness.MustDrawSolidQuad();
5263 harness.MustSetNoScissor();
5265 LayerTreeHostImpl::FrameData frame;
5266 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5267 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5268 host_impl_->DidDrawAllLayers(frame);
5270 Mock::VerifyAndClearExpectations(&mock_context);
5272 // Without partial swap, but a layer does clip its subtree, one scissor is
5273 // set.
5274 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5275 harness.MustDrawSolidQuad();
5276 harness.MustSetScissor(0, 0, 10, 10);
5278 LayerTreeHostImpl::FrameData frame;
5279 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5280 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5281 host_impl_->DidDrawAllLayers(frame);
5283 Mock::VerifyAndClearExpectations(&mock_context);
5286 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5287 scoped_ptr<MockContext> context_owned(new MockContext);
5288 MockContext* mock_context = context_owned.get();
5289 MockContextHarness harness(mock_context);
5291 LayerTreeSettings settings = DefaultSettings();
5292 settings.renderer_settings.partial_swap_enabled = true;
5293 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5294 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5296 // The first frame is not a partially-swapped one. No scissor should be set.
5297 harness.MustSetNoScissor();
5298 harness.MustDrawSolidQuad();
5300 LayerTreeHostImpl::FrameData frame;
5301 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5302 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5303 host_impl_->DidDrawAllLayers(frame);
5305 Mock::VerifyAndClearExpectations(&mock_context);
5307 // Damage a portion of the frame.
5308 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5309 gfx::Rect(0, 0, 2, 3));
5311 // The second frame will be partially-swapped (the y coordinates are flipped).
5312 harness.MustSetScissor(0, 7, 2, 3);
5313 harness.MustDrawSolidQuad();
5315 LayerTreeHostImpl::FrameData frame;
5316 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5317 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5318 host_impl_->DidDrawAllLayers(frame);
5320 Mock::VerifyAndClearExpectations(&mock_context);
5323 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5324 bool partial_swap,
5325 LayerTreeHostImplClient* client,
5326 Proxy* proxy,
5327 SharedBitmapManager* manager,
5328 RenderingStatsInstrumentation* stats_instrumentation) {
5329 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5330 scoped_ptr<OutputSurface> output_surface(
5331 FakeOutputSurface::Create3d(provider));
5332 provider->BindToCurrentThread();
5333 provider->TestContext3d()->set_have_post_sub_buffer(true);
5335 LayerTreeSettings settings;
5336 settings.renderer_settings.partial_swap_enabled = partial_swap;
5337 scoped_ptr<LayerTreeHostImpl> my_host_impl = LayerTreeHostImpl::Create(
5338 settings, client, proxy, stats_instrumentation, manager, NULL, NULL, 0);
5339 my_host_impl->InitializeRenderer(output_surface.Pass());
5340 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5343 Layers are created as follows:
5345 +--------------------+
5346 | 1 |
5347 | +-----------+ |
5348 | | 2 | |
5349 | | +-------------------+
5350 | | | 3 |
5351 | | +-------------------+
5352 | | | |
5353 | +-----------+ |
5356 +--------------------+
5358 Layers 1, 2 have render surfaces
5360 scoped_ptr<LayerImpl> root =
5361 LayerImpl::Create(my_host_impl->active_tree(), 1);
5362 scoped_ptr<LayerImpl> child =
5363 LayerImpl::Create(my_host_impl->active_tree(), 2);
5364 scoped_ptr<LayerImpl> grand_child =
5365 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5367 gfx::Rect root_rect(0, 0, 100, 100);
5368 gfx::Rect child_rect(10, 10, 50, 50);
5369 gfx::Rect grand_child_rect(5, 5, 150, 150);
5371 root->SetHasRenderSurface(true);
5372 root->SetPosition(root_rect.origin());
5373 root->SetBounds(root_rect.size());
5374 root->SetContentBounds(root->bounds());
5375 root->draw_properties().visible_content_rect = root_rect;
5376 root->SetDrawsContent(false);
5377 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5379 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5380 child->SetOpacity(0.5f);
5381 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5382 child->SetContentBounds(child->bounds());
5383 child->draw_properties().visible_content_rect = child_rect;
5384 child->SetDrawsContent(false);
5385 child->SetHasRenderSurface(true);
5387 grand_child->SetPosition(grand_child_rect.origin());
5388 grand_child->SetBounds(grand_child_rect.size());
5389 grand_child->SetContentBounds(grand_child->bounds());
5390 grand_child->draw_properties().visible_content_rect = grand_child_rect;
5391 grand_child->SetDrawsContent(true);
5393 child->AddChild(grand_child.Pass());
5394 root->AddChild(child.Pass());
5396 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5397 return my_host_impl.Pass();
5400 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5401 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5402 new TestSharedBitmapManager());
5403 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5404 SetupLayersForOpacity(true,
5405 this,
5406 &proxy_,
5407 shared_bitmap_manager.get(),
5408 &stats_instrumentation_);
5410 LayerTreeHostImpl::FrameData frame;
5411 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5413 // Verify all quads have been computed
5414 ASSERT_EQ(2U, frame.render_passes.size());
5415 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5416 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5417 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5418 frame.render_passes[0]->quad_list.front()->material);
5419 EXPECT_EQ(DrawQuad::RENDER_PASS,
5420 frame.render_passes[1]->quad_list.front()->material);
5422 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5423 my_host_impl->DidDrawAllLayers(frame);
5427 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5428 scoped_ptr<SharedBitmapManager> shared_bitmap_manager(
5429 new TestSharedBitmapManager());
5430 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5431 SetupLayersForOpacity(false,
5432 this,
5433 &proxy_,
5434 shared_bitmap_manager.get(),
5435 &stats_instrumentation_);
5437 LayerTreeHostImpl::FrameData frame;
5438 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5440 // Verify all quads have been computed
5441 ASSERT_EQ(2U, frame.render_passes.size());
5442 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5443 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5444 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5445 frame.render_passes[0]->quad_list.front()->material);
5446 EXPECT_EQ(DrawQuad::RENDER_PASS,
5447 frame.render_passes[1]->quad_list.front()->material);
5449 my_host_impl->DrawLayers(&frame, gfx::FrameTime::Now());
5450 my_host_impl->DidDrawAllLayers(frame);
5454 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
5455 scoped_ptr<TestWebGraphicsContext3D> context =
5456 TestWebGraphicsContext3D::Create();
5457 TestWebGraphicsContext3D* context3d = context.get();
5458 scoped_ptr<OutputSurface> output_surface(
5459 FakeOutputSurface::Create3d(context.Pass()));
5460 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5462 scoped_ptr<LayerImpl> root_layer =
5463 LayerImpl::Create(host_impl_->active_tree(), 1);
5464 root_layer->SetBounds(gfx::Size(10, 10));
5465 root_layer->SetHasRenderSurface(true);
5467 scoped_refptr<VideoFrame> softwareFrame =
5468 media::VideoFrame::CreateColorFrame(
5469 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5470 FakeVideoFrameProvider provider;
5471 provider.set_frame(softwareFrame);
5472 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5473 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
5474 video_layer->SetBounds(gfx::Size(10, 10));
5475 video_layer->SetContentBounds(gfx::Size(10, 10));
5476 video_layer->SetDrawsContent(true);
5477 root_layer->AddChild(video_layer.Pass());
5479 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
5480 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
5481 io_surface_layer->SetBounds(gfx::Size(10, 10));
5482 io_surface_layer->SetContentBounds(gfx::Size(10, 10));
5483 io_surface_layer->SetDrawsContent(true);
5484 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5485 root_layer->AddChild(io_surface_layer.Pass());
5487 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
5489 EXPECT_EQ(0u, context3d->NumTextures());
5491 LayerTreeHostImpl::FrameData frame;
5492 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5493 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5494 host_impl_->DidDrawAllLayers(frame);
5495 host_impl_->SwapBuffers(frame);
5497 EXPECT_GT(context3d->NumTextures(), 0u);
5499 // Kill the layer tree.
5500 host_impl_->active_tree()->SetRootLayer(
5501 LayerImpl::Create(host_impl_->active_tree(), 100));
5502 // There should be no textures left in use after.
5503 EXPECT_EQ(0u, context3d->NumTextures());
5506 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
5507 public:
5508 MOCK_METHOD1(useProgram, void(GLuint program));
5509 MOCK_METHOD4(drawElements, void(GLenum mode,
5510 GLsizei count,
5511 GLenum type,
5512 GLintptr offset));
5515 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
5516 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
5517 new MockDrawQuadsToFillScreenContext);
5518 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
5520 // Run test case
5521 LayerTreeSettings settings = DefaultSettings();
5522 settings.renderer_settings.partial_swap_enabled = false;
5523 CreateHostImpl(settings,
5524 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5525 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5526 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
5528 // Verify one quad is drawn when transparent background set is not set.
5529 host_impl_->active_tree()->set_has_transparent_background(false);
5530 EXPECT_CALL(*mock_context, useProgram(_))
5531 .Times(1);
5532 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
5533 .Times(1);
5534 LayerTreeHostImpl::FrameData frame;
5535 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5536 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5537 host_impl_->DidDrawAllLayers(frame);
5538 Mock::VerifyAndClearExpectations(&mock_context);
5540 // Verify no quads are drawn when transparent background is set.
5541 host_impl_->active_tree()->set_has_transparent_background(true);
5542 host_impl_->SetFullRootLayerDamage();
5543 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5544 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5545 host_impl_->DidDrawAllLayers(frame);
5546 Mock::VerifyAndClearExpectations(&mock_context);
5549 TEST_F(LayerTreeHostImplTest, ReleaseContentsTextureShouldTriggerCommit) {
5550 set_reduce_memory_result(false);
5552 // If changing the memory limit wouldn't result in changing what was
5553 // committed, then no commit should be requested.
5554 set_reduce_memory_result(false);
5555 host_impl_->set_max_memory_needed_bytes(
5556 host_impl_->memory_allocation_limit_bytes() - 1);
5557 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5558 host_impl_->memory_allocation_limit_bytes() - 1));
5559 EXPECT_FALSE(did_request_commit_);
5560 did_request_commit_ = false;
5562 // If changing the memory limit would result in changing what was
5563 // committed, then a commit should be requested, even though nothing was
5564 // evicted.
5565 set_reduce_memory_result(false);
5566 host_impl_->set_max_memory_needed_bytes(
5567 host_impl_->memory_allocation_limit_bytes());
5568 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5569 host_impl_->memory_allocation_limit_bytes() - 1));
5570 EXPECT_TRUE(did_request_commit_);
5571 did_request_commit_ = false;
5573 // Especially if changing the memory limit caused evictions, we need
5574 // to re-commit.
5575 set_reduce_memory_result(true);
5576 host_impl_->set_max_memory_needed_bytes(1);
5577 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5578 host_impl_->memory_allocation_limit_bytes() - 1));
5579 EXPECT_TRUE(did_request_commit_);
5580 did_request_commit_ = false;
5582 // But if we set it to the same value that it was before, we shouldn't
5583 // re-commit.
5584 host_impl_->SetMemoryPolicy(ManagedMemoryPolicy(
5585 host_impl_->memory_allocation_limit_bytes()));
5586 EXPECT_FALSE(did_request_commit_);
5589 class LayerTreeHostImplTestWithDelegatingRenderer
5590 : public LayerTreeHostImplTest {
5591 protected:
5592 scoped_ptr<OutputSurface> CreateOutputSurface() override {
5593 return FakeOutputSurface::CreateDelegating3d();
5596 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
5597 bool expect_to_draw = !expected_damage.IsEmpty();
5599 LayerTreeHostImpl::FrameData frame;
5600 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5602 if (!expect_to_draw) {
5603 // With no damage, we don't draw, and no quads are created.
5604 ASSERT_EQ(0u, frame.render_passes.size());
5605 } else {
5606 ASSERT_EQ(1u, frame.render_passes.size());
5608 // Verify the damage rect for the root render pass.
5609 const RenderPass* root_render_pass = frame.render_passes.back();
5610 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
5612 // Verify the root and child layers' quads are generated and not being
5613 // culled.
5614 ASSERT_EQ(2u, root_render_pass->quad_list.size());
5616 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
5617 gfx::RectF expected_child_visible_rect(child->content_bounds());
5618 EXPECT_EQ(expected_child_visible_rect,
5619 root_render_pass->quad_list.front()->visible_rect);
5621 LayerImpl* root = host_impl_->active_tree()->root_layer();
5622 gfx::RectF expected_root_visible_rect(root->content_bounds());
5623 EXPECT_EQ(expected_root_visible_rect,
5624 root_render_pass->quad_list.ElementAt(1)->visible_rect);
5627 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5628 host_impl_->DidDrawAllLayers(frame);
5629 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
5633 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
5634 scoped_ptr<SolidColorLayerImpl> root =
5635 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5636 root->SetPosition(gfx::PointF());
5637 root->SetBounds(gfx::Size(10, 10));
5638 root->SetContentBounds(gfx::Size(10, 10));
5639 root->SetDrawsContent(true);
5640 root->SetHasRenderSurface(true);
5642 // Child layer is in the bottom right corner.
5643 scoped_ptr<SolidColorLayerImpl> child =
5644 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
5645 child->SetPosition(gfx::PointF(9.f, 9.f));
5646 child->SetBounds(gfx::Size(1, 1));
5647 child->SetContentBounds(gfx::Size(1, 1));
5648 child->SetDrawsContent(true);
5649 root->AddChild(child.Pass());
5651 host_impl_->active_tree()->SetRootLayer(root.Pass());
5653 // Draw a frame. In the first frame, the entire viewport should be damaged.
5654 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5655 DrawFrameAndTestDamage(full_frame_damage);
5657 // The second frame has damage that doesn't touch the child layer. Its quads
5658 // should still be generated.
5659 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
5660 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
5661 DrawFrameAndTestDamage(small_damage);
5663 // The third frame should have no damage, so no quads should be generated.
5664 gfx::Rect no_damage;
5665 DrawFrameAndTestDamage(no_damage);
5668 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5669 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5670 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
5671 LayerTreeSettings settings;
5672 CreateHostImpl(settings, CreateOutputSurface());
5673 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
5676 class FakeMaskLayerImpl : public LayerImpl {
5677 public:
5678 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
5679 int id) {
5680 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
5683 void GetContentsResourceId(ResourceProvider::ResourceId* resource_id,
5684 gfx::Size* resource_size) const override {
5685 *resource_id = 0;
5688 private:
5689 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
5690 : LayerImpl(tree_impl, id) {}
5693 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5694 public:
5695 using GLRenderer::ShouldAntialiasQuad;
5698 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5699 // Due to precision issues (especially on Android), sometimes far
5700 // away quads can end up thinking they need AA.
5701 float device_scale_factor = 4.f / 3.f;
5702 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5703 gfx::Size root_size(2000, 1000);
5704 gfx::Size device_viewport_size =
5705 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5706 host_impl_->SetViewportSize(device_viewport_size);
5708 host_impl_->CreatePendingTree();
5709 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
5710 16.f);
5712 scoped_ptr<LayerImpl> scoped_root =
5713 LayerImpl::Create(host_impl_->pending_tree(), 1);
5714 LayerImpl* root = scoped_root.get();
5715 root->SetHasRenderSurface(true);
5717 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5719 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5720 LayerImpl::Create(host_impl_->pending_tree(), 2);
5721 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5722 root->AddChild(scoped_scrolling_layer.Pass());
5724 gfx::Size content_layer_bounds(100000, 100);
5725 gfx::Size pile_tile_size(3000, 3000);
5726 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5727 pile_tile_size, content_layer_bounds));
5729 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5730 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
5731 3, pile);
5732 LayerImpl* content_layer = scoped_content_layer.get();
5733 scrolling_layer->AddChild(scoped_content_layer.Pass());
5734 content_layer->SetBounds(content_layer_bounds);
5735 content_layer->SetDrawsContent(true);
5737 root->SetBounds(root_size);
5739 gfx::ScrollOffset scroll_offset(100000, 0);
5740 scrolling_layer->SetScrollClipLayer(root->id());
5741 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
5743 host_impl_->ActivateSyncTree();
5745 bool update_lcd_text = false;
5746 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
5747 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5749 LayerTreeHostImpl::FrameData frame;
5750 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5752 ASSERT_EQ(1u, frame.render_passes.size());
5753 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5754 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
5756 bool antialiased =
5757 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
5758 quad->quadTransform(), quad, false);
5759 EXPECT_FALSE(antialiased);
5761 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5762 host_impl_->DidDrawAllLayers(frame);
5766 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
5767 public:
5768 CompositorFrameMetadataTest()
5769 : swap_buffers_complete_(0) {}
5771 void DidSwapBuffersCompleteOnImplThread() override {
5772 swap_buffers_complete_++;
5775 int swap_buffers_complete_;
5778 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
5779 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5781 LayerTreeHostImpl::FrameData frame;
5782 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5783 host_impl_->DrawLayers(&frame, base::TimeTicks());
5784 host_impl_->DidDrawAllLayers(frame);
5786 CompositorFrameAck ack;
5787 host_impl_->ReclaimResources(&ack);
5788 host_impl_->DidSwapBuffersComplete();
5789 EXPECT_EQ(swap_buffers_complete_, 1);
5792 class CountingSoftwareDevice : public SoftwareOutputDevice {
5793 public:
5794 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5796 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
5797 ++frames_began_;
5798 return SoftwareOutputDevice::BeginPaint(damage_rect);
5800 void EndPaint(SoftwareFrameData* frame_data) override {
5801 ++frames_ended_;
5802 SoftwareOutputDevice::EndPaint(frame_data);
5805 int frames_began_, frames_ended_;
5808 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
5809 // No main thread evictions in resourceless software mode.
5810 set_reduce_memory_result(false);
5811 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
5812 EXPECT_TRUE(CreateHostImpl(
5813 DefaultSettings(),
5814 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device))));
5815 host_impl_->SetViewportSize(gfx::Size(50, 50));
5817 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5819 const gfx::Transform external_transform;
5820 const gfx::Rect external_viewport;
5821 const gfx::Rect external_clip;
5822 const bool resourceless_software_draw = true;
5823 host_impl_->SetExternalDrawConstraints(external_transform,
5824 external_viewport,
5825 external_clip,
5826 external_viewport,
5827 external_transform,
5828 resourceless_software_draw);
5830 EXPECT_EQ(0, software_device->frames_began_);
5831 EXPECT_EQ(0, software_device->frames_ended_);
5833 DrawFrame();
5835 EXPECT_EQ(1, software_device->frames_began_);
5836 EXPECT_EQ(1, software_device->frames_ended_);
5838 // Call another API method that is likely to hit nullptr in this mode.
5839 scoped_refptr<base::trace_event::TracedValue> state =
5840 make_scoped_refptr(new base::trace_event::TracedValue());
5841 host_impl_->ActivationStateAsValueInto(state.get());
5844 TEST_F(LayerTreeHostImplTest,
5845 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
5846 set_reduce_memory_result(false);
5847 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5848 FakeOutputSurface::CreateSoftware(
5849 make_scoped_ptr(new CountingSoftwareDevice))));
5851 const gfx::Transform external_transform;
5852 const gfx::Rect external_viewport;
5853 const gfx::Rect external_clip;
5854 const bool resourceless_software_draw = true;
5855 host_impl_->SetExternalDrawConstraints(external_transform,
5856 external_viewport,
5857 external_clip,
5858 external_viewport,
5859 external_transform,
5860 resourceless_software_draw);
5862 // SolidColorLayerImpl will be drawn.
5863 scoped_ptr<SolidColorLayerImpl> root_layer =
5864 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5866 // VideoLayerImpl will not be drawn.
5867 FakeVideoFrameProvider provider;
5868 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5869 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
5870 video_layer->SetBounds(gfx::Size(10, 10));
5871 video_layer->SetContentBounds(gfx::Size(10, 10));
5872 video_layer->SetDrawsContent(true);
5873 root_layer->AddChild(video_layer.Pass());
5874 SetupRootLayerImpl(root_layer.Pass());
5876 LayerTreeHostImpl::FrameData frame;
5877 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5878 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
5879 host_impl_->DidDrawAllLayers(frame);
5881 EXPECT_EQ(1u, frame.will_draw_layers.size());
5882 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
5885 // Checks that we have a non-0 default allocation if we pass a context that
5886 // doesn't support memory management extensions.
5887 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
5888 LayerTreeSettings settings;
5889 host_impl_ = LayerTreeHostImpl::Create(
5890 settings, this, &proxy_, &stats_instrumentation_,
5891 shared_bitmap_manager_.get(), gpu_memory_buffer_manager_.get(),
5892 task_graph_runner_.get(), 0);
5894 scoped_ptr<OutputSurface> output_surface(
5895 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5896 host_impl_->InitializeRenderer(output_surface.Pass());
5897 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
5900 TEST_F(LayerTreeHostImplTest, MemoryPolicy) {
5901 ManagedMemoryPolicy policy1(
5902 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING, 1000);
5903 int everything_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5904 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING);
5905 int allow_nice_to_have_cutoff_value =
5906 ManagedMemoryPolicy::PriorityCutoffToValue(
5907 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE);
5908 int nothing_cutoff_value = ManagedMemoryPolicy::PriorityCutoffToValue(
5909 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING);
5911 // GPU rasterization should be disabled by default on the tree(s)
5912 EXPECT_FALSE(host_impl_->active_tree()->use_gpu_rasterization());
5913 EXPECT_TRUE(host_impl_->pending_tree() == NULL);
5915 host_impl_->SetVisible(true);
5916 host_impl_->SetMemoryPolicy(policy1);
5917 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5918 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5920 host_impl_->SetVisible(false);
5921 EXPECT_EQ(0u, current_limit_bytes_);
5922 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5924 host_impl_->SetVisible(true);
5925 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5926 EXPECT_EQ(everything_cutoff_value, current_priority_cutoff_value_);
5928 // Now enable GPU rasterization and test if we get nice to have cutoff,
5929 // when visible.
5930 LayerTreeSettings settings;
5931 settings.gpu_rasterization_enabled = true;
5932 host_impl_ = LayerTreeHostImpl::Create(
5933 settings, this, &proxy_, &stats_instrumentation_, NULL, NULL, NULL, 0);
5934 host_impl_->SetUseGpuRasterization(true);
5935 host_impl_->SetVisible(true);
5936 host_impl_->SetMemoryPolicy(policy1);
5937 EXPECT_EQ(policy1.bytes_limit_when_visible, current_limit_bytes_);
5938 EXPECT_EQ(allow_nice_to_have_cutoff_value, current_priority_cutoff_value_);
5940 host_impl_->SetVisible(false);
5941 EXPECT_EQ(0u, current_limit_bytes_);
5942 EXPECT_EQ(nothing_cutoff_value, current_priority_cutoff_value_);
5945 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
5946 ASSERT_TRUE(host_impl_->active_tree());
5948 // RequiresHighResToDraw is set when new output surface is used.
5949 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5951 host_impl_->ResetRequiresHighResToDraw();
5953 host_impl_->SetVisible(false);
5954 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
5955 host_impl_->SetVisible(true);
5956 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5957 host_impl_->SetVisible(false);
5958 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5960 host_impl_->ResetRequiresHighResToDraw();
5962 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
5963 host_impl_->SetVisible(true);
5964 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5967 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
5968 ASSERT_TRUE(host_impl_->active_tree());
5969 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
5971 // RequiresHighResToDraw is set when new output surface is used.
5972 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5974 host_impl_->ResetRequiresHighResToDraw();
5976 host_impl_->SetUseGpuRasterization(false);
5977 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
5978 host_impl_->SetUseGpuRasterization(true);
5979 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5980 host_impl_->SetUseGpuRasterization(false);
5981 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5983 host_impl_->ResetRequiresHighResToDraw();
5985 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
5986 host_impl_->SetUseGpuRasterization(true);
5987 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
5990 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
5991 public:
5992 void SetUp() override {
5993 LayerTreeSettings settings;
5994 settings.impl_side_painting = true;
5996 fake_host_impl_ = new FakeLayerTreeHostImpl(settings, &proxy_,
5997 shared_bitmap_manager_.get(),
5998 task_graph_runner_.get());
5999 host_impl_.reset(fake_host_impl_);
6000 host_impl_->InitializeRenderer(CreateOutputSurface());
6001 host_impl_->SetViewportSize(gfx::Size(10, 10));
6004 FakeLayerTreeHostImpl* fake_host_impl_;
6007 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6008 fake_host_impl_->DidModifyTilePriorities();
6009 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6010 fake_host_impl_->SetVisible(false);
6011 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6014 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6015 scoped_ptr<TestWebGraphicsContext3D> context =
6016 TestWebGraphicsContext3D::Create();
6017 TestWebGraphicsContext3D* context3d = context.get();
6018 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6019 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6021 EXPECT_EQ(0u, context3d->NumTextures());
6023 UIResourceId ui_resource_id = 1;
6024 bool is_opaque = false;
6025 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6026 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6027 EXPECT_EQ(1u, context3d->NumTextures());
6028 ResourceProvider::ResourceId id1 =
6029 host_impl_->ResourceIdForUIResource(ui_resource_id);
6030 EXPECT_NE(0u, id1);
6032 // Multiple requests with the same id is allowed. The previous texture is
6033 // deleted.
6034 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6035 EXPECT_EQ(1u, context3d->NumTextures());
6036 ResourceProvider::ResourceId id2 =
6037 host_impl_->ResourceIdForUIResource(ui_resource_id);
6038 EXPECT_NE(0u, id2);
6039 EXPECT_NE(id1, id2);
6041 // Deleting invalid UIResourceId is allowed and does not change state.
6042 host_impl_->DeleteUIResource(-1);
6043 EXPECT_EQ(1u, context3d->NumTextures());
6045 // Should return zero for invalid UIResourceId. Number of textures should
6046 // not change.
6047 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6048 EXPECT_EQ(1u, context3d->NumTextures());
6050 host_impl_->DeleteUIResource(ui_resource_id);
6051 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6052 EXPECT_EQ(0u, context3d->NumTextures());
6054 // Should not change state for multiple deletion on one UIResourceId
6055 host_impl_->DeleteUIResource(ui_resource_id);
6056 EXPECT_EQ(0u, context3d->NumTextures());
6059 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6060 scoped_ptr<TestWebGraphicsContext3D> context =
6061 TestWebGraphicsContext3D::Create();
6062 TestWebGraphicsContext3D* context3d = context.get();
6063 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6065 EXPECT_EQ(0u, context3d->NumTextures());
6067 gfx::Size size(4, 4);
6068 // SkImageInfo has no support for ETC1. The |info| below contains the right
6069 // total pixel size for the bitmap but not the right height and width. The
6070 // correct width/height are passed directly to UIResourceBitmap.
6071 SkImageInfo info =
6072 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6073 skia::RefPtr<SkPixelRef> pixel_ref =
6074 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6075 pixel_ref->setImmutable();
6076 UIResourceBitmap bitmap(pixel_ref, size);
6077 UIResourceId ui_resource_id = 1;
6078 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6079 EXPECT_EQ(1u, context3d->NumTextures());
6080 ResourceProvider::ResourceId id1 =
6081 host_impl_->ResourceIdForUIResource(ui_resource_id);
6082 EXPECT_NE(0u, id1);
6085 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6088 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6089 scoped_refptr<TestContextProvider> context_provider =
6090 TestContextProvider::Create();
6092 CreateHostImpl(DefaultSettings(),
6093 FakeOutputSurface::Create3d(context_provider));
6095 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6097 ScopedPtrVector<CopyOutputRequest> requests;
6098 requests.push_back(CopyOutputRequest::CreateRequest(
6099 base::Bind(&ShutdownReleasesContext_Callback)));
6101 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6103 LayerTreeHostImpl::FrameData frame;
6104 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6105 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6106 host_impl_->DidDrawAllLayers(frame);
6108 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6109 // texture in a texture mailbox.
6110 EXPECT_FALSE(context_provider->HasOneRef());
6111 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6113 host_impl_ = nullptr;
6115 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6116 // released, and the texture deleted.
6117 EXPECT_TRUE(context_provider->HasOneRef());
6118 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6121 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6122 // When flinging via touch, only the child should scroll (we should not
6123 // bubble).
6124 gfx::Size surface_size(10, 10);
6125 gfx::Size content_size(20, 20);
6126 scoped_ptr<LayerImpl> root_clip =
6127 LayerImpl::Create(host_impl_->active_tree(), 3);
6128 root_clip->SetHasRenderSurface(true);
6130 scoped_ptr<LayerImpl> root =
6131 CreateScrollableLayer(1, content_size, root_clip.get());
6132 root->SetIsContainerForFixedPositionLayers(true);
6133 scoped_ptr<LayerImpl> child =
6134 CreateScrollableLayer(2, content_size, root_clip.get());
6136 root->AddChild(child.Pass());
6137 int root_id = root->id();
6138 root_clip->AddChild(root.Pass());
6140 host_impl_->SetViewportSize(surface_size);
6141 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6142 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6143 Layer::INVALID_ID);
6144 host_impl_->active_tree()->DidBecomeActive();
6145 DrawFrame();
6147 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6148 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6150 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6152 gfx::Vector2d scroll_delta(0, 100);
6153 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6154 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6156 host_impl_->ScrollEnd();
6158 scoped_ptr<ScrollAndScaleSet> scroll_info =
6159 host_impl_->ProcessScrollDeltas();
6161 // Only the child should have scrolled.
6162 ASSERT_EQ(1u, scroll_info->scrolls.size());
6163 ExpectNone(*scroll_info.get(), root_id);
6167 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6168 // Scroll a child layer beyond its maximum scroll range and make sure the
6169 // the scroll doesn't bubble up to the parent layer.
6170 gfx::Size surface_size(10, 10);
6171 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6172 root->SetHasRenderSurface(true);
6173 scoped_ptr<LayerImpl> root_scrolling =
6174 CreateScrollableLayer(2, surface_size, root.get());
6176 scoped_ptr<LayerImpl> grand_child =
6177 CreateScrollableLayer(4, surface_size, root.get());
6178 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6180 scoped_ptr<LayerImpl> child =
6181 CreateScrollableLayer(3, surface_size, root.get());
6182 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6183 child->AddChild(grand_child.Pass());
6185 root_scrolling->AddChild(child.Pass());
6186 root->AddChild(root_scrolling.Pass());
6187 host_impl_->active_tree()->SetRootLayer(root.Pass());
6188 host_impl_->active_tree()->DidBecomeActive();
6189 host_impl_->SetViewportSize(surface_size);
6190 DrawFrame();
6192 scoped_ptr<ScrollAndScaleSet> scroll_info;
6193 LayerImpl* child =
6194 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6195 LayerImpl* grand_child = child->children()[0];
6197 gfx::Vector2d scroll_delta(0, -2);
6198 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6199 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6200 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6202 // The grand child should have scrolled up to its limit.
6203 scroll_info = host_impl_->ProcessScrollDeltas();
6204 ASSERT_EQ(1u, scroll_info->scrolls.size());
6205 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6206 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6208 // The child should have received the bubbled delta, but the locked
6209 // scrolling layer should remain set as the grand child.
6210 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6211 scroll_info = host_impl_->ProcessScrollDeltas();
6212 ASSERT_EQ(2u, scroll_info->scrolls.size());
6213 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6214 ExpectContains(*scroll_info, child->id(), scroll_delta);
6215 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6217 // The first |ScrollBy| after the fling should re-lock the scrolling
6218 // layer to the first layer that scrolled, which is the child.
6219 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6220 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6221 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6223 // The child should have scrolled up to its limit.
6224 scroll_info = host_impl_->ProcessScrollDeltas();
6225 ASSERT_EQ(2u, scroll_info->scrolls.size());
6226 ExpectContains(*scroll_info, grand_child->id(), scroll_delta);
6227 ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta);
6229 // As the locked layer is at it's limit, no further scrolling can occur.
6230 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6231 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6232 host_impl_->ScrollEnd();
6236 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6237 // When flinging via wheel, the root should eventually scroll (we should
6238 // bubble).
6239 gfx::Size surface_size(10, 10);
6240 gfx::Size content_size(20, 20);
6241 scoped_ptr<LayerImpl> root_clip =
6242 LayerImpl::Create(host_impl_->active_tree(), 3);
6243 root_clip->SetHasRenderSurface(true);
6244 scoped_ptr<LayerImpl> root_scroll =
6245 CreateScrollableLayer(1, content_size, root_clip.get());
6246 int root_scroll_id = root_scroll->id();
6247 scoped_ptr<LayerImpl> child =
6248 CreateScrollableLayer(2, content_size, root_clip.get());
6250 root_scroll->AddChild(child.Pass());
6251 root_clip->AddChild(root_scroll.Pass());
6253 host_impl_->SetViewportSize(surface_size);
6254 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6255 host_impl_->active_tree()->DidBecomeActive();
6256 DrawFrame();
6258 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6259 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6261 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6263 gfx::Vector2d scroll_delta(0, 100);
6264 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6265 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6267 host_impl_->ScrollEnd();
6269 scoped_ptr<ScrollAndScaleSet> scroll_info =
6270 host_impl_->ProcessScrollDeltas();
6272 // The root should have scrolled.
6273 ASSERT_EQ(2u, scroll_info->scrolls.size());
6274 ExpectContains(*scroll_info.get(), root_scroll_id, gfx::Vector2d(0, 10));
6278 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6279 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6280 // we should return SCROLL_UNKNOWN.
6281 gfx::Size content_size(100, 100);
6282 SetupScrollAndContentsLayers(content_size);
6284 int scroll_layer_id = 2;
6285 LayerImpl* scroll_layer =
6286 host_impl_->active_tree()->LayerById(scroll_layer_id);
6287 scroll_layer->SetDrawsContent(true);
6289 int page_scale_layer_id = 5;
6290 LayerImpl* page_scale_layer =
6291 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6293 int occluder_layer_id = 6;
6294 scoped_ptr<LayerImpl> occluder_layer =
6295 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6296 occluder_layer->SetDrawsContent(true);
6297 occluder_layer->SetBounds(content_size);
6298 occluder_layer->SetContentBounds(content_size);
6299 occluder_layer->SetPosition(gfx::PointF());
6301 // The parent of the occluder is *above* the scroller.
6302 page_scale_layer->AddChild(occluder_layer.Pass());
6304 DrawFrame();
6306 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6307 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6310 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6311 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6312 // is not the first scroller we encounter when walking up from the layer, we
6313 // should also return SCROLL_UNKNOWN.
6314 gfx::Size content_size(100, 100);
6315 SetupScrollAndContentsLayers(content_size);
6317 int scroll_layer_id = 2;
6318 LayerImpl* scroll_layer =
6319 host_impl_->active_tree()->LayerById(scroll_layer_id);
6320 scroll_layer->SetDrawsContent(true);
6322 int occluder_layer_id = 6;
6323 scoped_ptr<LayerImpl> occluder_layer =
6324 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6325 occluder_layer->SetDrawsContent(true);
6326 occluder_layer->SetBounds(content_size);
6327 occluder_layer->SetContentBounds(content_size);
6328 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6330 int child_scroll_clip_layer_id = 7;
6331 scoped_ptr<LayerImpl> child_scroll_clip =
6332 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6334 int child_scroll_layer_id = 8;
6335 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6336 child_scroll_layer_id, content_size, child_scroll_clip.get());
6338 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6340 child_scroll->AddChild(occluder_layer.Pass());
6341 scroll_layer->AddChild(child_scroll.Pass());
6343 DrawFrame();
6345 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6346 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6349 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
6350 gfx::Size content_size(100, 100);
6351 SetupScrollAndContentsLayers(content_size);
6353 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6355 int scroll_layer_id = 2;
6356 LayerImpl* scroll_layer =
6357 host_impl_->active_tree()->LayerById(scroll_layer_id);
6359 int child_scroll_layer_id = 7;
6360 scoped_ptr<LayerImpl> child_scroll =
6361 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6362 child_scroll->SetDrawsContent(false);
6364 scroll_layer->AddChild(child_scroll.Pass());
6366 DrawFrame();
6368 // We should not have scrolled |child_scroll| even though we technically "hit"
6369 // it. The reason for this is that if the scrolling the scroll would not move
6370 // any layer that is a drawn RSLL member, then we can ignore the hit.
6372 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6373 // started scrolling the inner viewport.
6374 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6375 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6377 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6380 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
6381 gfx::Size content_size(100, 100);
6382 SetupScrollAndContentsLayers(content_size);
6384 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6385 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
6387 scoped_ptr<LayerImpl> invisible_scroll_layer =
6388 CreateScrollableLayer(7, content_size, root);
6389 invisible_scroll_layer->SetDrawsContent(false);
6391 scoped_ptr<LayerImpl> child_layer =
6392 LayerImpl::Create(host_impl_->active_tree(), 8);
6393 child_layer->SetDrawsContent(false);
6395 scoped_ptr<LayerImpl> grand_child_layer =
6396 LayerImpl::Create(host_impl_->active_tree(), 9);
6397 grand_child_layer->SetDrawsContent(true);
6398 grand_child_layer->SetBounds(content_size);
6399 grand_child_layer->SetContentBounds(content_size);
6400 // Move the grand child so it's not hit by our test point.
6401 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
6403 child_layer->AddChild(grand_child_layer.Pass());
6404 invisible_scroll_layer->AddChild(child_layer.Pass());
6405 root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
6407 DrawFrame();
6409 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6410 // a descendant which is a drawn RSLL member.
6411 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6412 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6414 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6417 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6418 // This test case is very similar to the one above with one key difference:
6419 // the invisible scroller has a scroll child that is indeed draw contents.
6420 // If we attempt to initiate a gesture scroll off of the visible scroll child
6421 // we should still start the scroll child.
6422 gfx::Size content_size(100, 100);
6423 SetupScrollAndContentsLayers(content_size);
6425 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6427 int scroll_layer_id = 2;
6428 LayerImpl* scroll_layer =
6429 host_impl_->active_tree()->LayerById(scroll_layer_id);
6431 int scroll_child_id = 6;
6432 scoped_ptr<LayerImpl> scroll_child =
6433 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6434 scroll_child->SetDrawsContent(true);
6435 scroll_child->SetBounds(content_size);
6436 scroll_child->SetContentBounds(content_size);
6437 // Move the scroll child so it's not hit by our test point.
6438 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6440 int invisible_scroll_layer_id = 7;
6441 scoped_ptr<LayerImpl> invisible_scroll =
6442 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6443 invisible_scroll->SetDrawsContent(false);
6445 int container_id = 8;
6446 scoped_ptr<LayerImpl> container =
6447 LayerImpl::Create(host_impl_->active_tree(), container_id);
6449 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6450 scroll_children->insert(scroll_child.get());
6451 invisible_scroll->SetScrollChildren(scroll_children.release());
6453 scroll_child->SetScrollParent(invisible_scroll.get());
6455 container->AddChild(invisible_scroll.Pass());
6456 container->AddChild(scroll_child.Pass());
6458 scroll_layer->AddChild(container.Pass());
6460 DrawFrame();
6462 // We should have scrolled |child_scroll| even though it is invisible.
6463 // The reason for this is that if the scrolling the scroll would move a layer
6464 // that is a drawn RSLL member, then we should accept this hit.
6465 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6466 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6468 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6471 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6472 // to CompositorFrameMetadata after SwapBuffers();
6473 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6474 scoped_ptr<SolidColorLayerImpl> root =
6475 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6476 root->SetPosition(gfx::PointF());
6477 root->SetBounds(gfx::Size(10, 10));
6478 root->SetContentBounds(gfx::Size(10, 10));
6479 root->SetDrawsContent(true);
6480 root->SetHasRenderSurface(true);
6482 host_impl_->active_tree()->SetRootLayer(root.Pass());
6484 FakeOutputSurface* fake_output_surface =
6485 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6487 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6488 fake_output_surface->last_sent_frame().metadata.latency_info;
6489 EXPECT_TRUE(metadata_latency_before.empty());
6491 ui::LatencyInfo latency_info;
6492 latency_info.AddLatencyNumber(
6493 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6494 scoped_ptr<SwapPromise> swap_promise(
6495 new LatencyInfoSwapPromise(latency_info));
6496 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6497 host_impl_->SetNeedsRedraw();
6499 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6500 LayerTreeHostImpl::FrameData frame;
6501 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6502 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6503 host_impl_->DidDrawAllLayers(frame);
6504 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6506 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6507 fake_output_surface->last_sent_frame().metadata.latency_info;
6508 EXPECT_EQ(1u, metadata_latency_after.size());
6509 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6510 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6513 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6514 int root_layer_id = 1;
6515 scoped_ptr<SolidColorLayerImpl> root =
6516 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6517 root->SetPosition(gfx::PointF());
6518 root->SetBounds(gfx::Size(10, 10));
6519 root->SetContentBounds(gfx::Size(10, 10));
6520 root->SetDrawsContent(true);
6521 root->SetHasRenderSurface(true);
6523 host_impl_->active_tree()->SetRootLayer(root.Pass());
6525 // Ensure the default frame selection bounds are empty.
6526 FakeOutputSurface* fake_output_surface =
6527 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6528 const ViewportSelection& selection_before =
6529 fake_output_surface->last_sent_frame().metadata.selection;
6530 EXPECT_EQ(ViewportSelectionBound(), selection_before.start);
6531 EXPECT_EQ(ViewportSelectionBound(), selection_before.end);
6533 // Plumb the layer-local selection bounds.
6534 gfx::PointF selection_top(5, 0);
6535 gfx::PointF selection_bottom(5, 5);
6536 LayerSelection selection;
6537 selection.start.type = SELECTION_BOUND_CENTER;
6538 selection.start.layer_id = root_layer_id;
6539 selection.start.edge_bottom = selection_bottom;
6540 selection.start.edge_top = selection_top;
6541 selection.end = selection.start;
6542 host_impl_->active_tree()->RegisterSelection(selection);
6544 // Trigger a draw-swap sequence.
6545 host_impl_->SetNeedsRedraw();
6547 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6548 LayerTreeHostImpl::FrameData frame;
6549 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6550 host_impl_->DrawLayers(&frame, gfx::FrameTime::Now());
6551 host_impl_->DidDrawAllLayers(frame);
6552 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6554 // Ensure the selection bounds have propagated to the frame metadata.
6555 const ViewportSelection& selection_after =
6556 fake_output_surface->last_sent_frame().metadata.selection;
6557 EXPECT_EQ(selection.start.type, selection_after.start.type);
6558 EXPECT_EQ(selection.end.type, selection_after.end.type);
6559 EXPECT_EQ(selection_bottom, selection_after.start.edge_bottom);
6560 EXPECT_EQ(selection_top, selection_after.start.edge_top);
6561 EXPECT_TRUE(selection_after.start.visible);
6562 EXPECT_TRUE(selection_after.start.visible);
6565 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6566 public:
6567 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6568 LayerTreeHostImpl* layer_tree_host_impl,
6569 int* set_needs_commit_count,
6570 int* set_needs_redraw_count,
6571 int* forward_to_main_count)
6572 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6573 set_needs_commit_count_(set_needs_commit_count),
6574 set_needs_redraw_count_(set_needs_redraw_count),
6575 forward_to_main_count_(forward_to_main_count) {}
6577 ~SimpleSwapPromiseMonitor() override {}
6579 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
6581 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
6583 void OnForwardScrollUpdateToMainThreadOnImpl() override {
6584 (*forward_to_main_count_)++;
6587 private:
6588 int* set_needs_commit_count_;
6589 int* set_needs_redraw_count_;
6590 int* forward_to_main_count_;
6593 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6594 int set_needs_commit_count = 0;
6595 int set_needs_redraw_count = 0;
6596 int forward_to_main_count = 0;
6599 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6600 new SimpleSwapPromiseMonitor(NULL,
6601 host_impl_.get(),
6602 &set_needs_commit_count,
6603 &set_needs_redraw_count,
6604 &forward_to_main_count));
6605 host_impl_->SetNeedsRedraw();
6606 EXPECT_EQ(0, set_needs_commit_count);
6607 EXPECT_EQ(1, set_needs_redraw_count);
6608 EXPECT_EQ(0, forward_to_main_count);
6611 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6612 // monitored.
6613 host_impl_->SetNeedsRedraw();
6614 EXPECT_EQ(0, set_needs_commit_count);
6615 EXPECT_EQ(1, set_needs_redraw_count);
6616 EXPECT_EQ(0, forward_to_main_count);
6619 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6620 new SimpleSwapPromiseMonitor(NULL,
6621 host_impl_.get(),
6622 &set_needs_commit_count,
6623 &set_needs_redraw_count,
6624 &forward_to_main_count));
6625 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6626 EXPECT_EQ(0, set_needs_commit_count);
6627 EXPECT_EQ(2, set_needs_redraw_count);
6628 EXPECT_EQ(0, forward_to_main_count);
6632 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6633 new SimpleSwapPromiseMonitor(NULL,
6634 host_impl_.get(),
6635 &set_needs_commit_count,
6636 &set_needs_redraw_count,
6637 &forward_to_main_count));
6638 // Empty damage rect won't signal the monitor.
6639 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6640 EXPECT_EQ(0, set_needs_commit_count);
6641 EXPECT_EQ(2, set_needs_redraw_count);
6642 EXPECT_EQ(0, forward_to_main_count);
6646 set_needs_commit_count = 0;
6647 set_needs_redraw_count = 0;
6648 forward_to_main_count = 0;
6649 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6650 new SimpleSwapPromiseMonitor(NULL,
6651 host_impl_.get(),
6652 &set_needs_commit_count,
6653 &set_needs_redraw_count,
6654 &forward_to_main_count));
6655 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
6657 // Scrolling normally should not trigger any forwarding.
6658 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6659 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6660 EXPECT_TRUE(
6661 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6662 host_impl_->ScrollEnd();
6664 EXPECT_EQ(0, set_needs_commit_count);
6665 EXPECT_EQ(1, set_needs_redraw_count);
6666 EXPECT_EQ(0, forward_to_main_count);
6668 // Scrolling with a scroll handler should defer the swap to the main
6669 // thread.
6670 scroll_layer->SetHaveScrollEventHandlers(true);
6671 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6672 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6673 EXPECT_TRUE(
6674 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6675 host_impl_->ScrollEnd();
6677 EXPECT_EQ(0, set_needs_commit_count);
6678 EXPECT_EQ(2, set_needs_redraw_count);
6679 EXPECT_EQ(1, forward_to_main_count);
6683 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6684 public:
6685 void SetUp() override {
6686 LayerTreeSettings settings = DefaultSettings();
6687 CreateHostImpl(settings, CreateOutputSurface());
6688 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
6689 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
6690 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
6693 protected:
6694 static const int top_controls_height_;
6697 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6699 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6700 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6701 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6702 host_impl_->Animate(base::TimeTicks());
6703 EXPECT_FALSE(did_request_redraw_);
6706 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
6707 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6708 EXPECT_FALSE(did_request_redraw_);
6709 host_impl_->CreatePendingTree();
6710 host_impl_->sync_tree()->set_top_controls_height(100);
6711 host_impl_->ActivateSyncTree();
6712 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
6715 TEST_F(LayerTreeHostImplWithTopControlsTest,
6716 TopControlsStayFullyVisibleOnHeightChange) {
6717 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6718 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6720 host_impl_->CreatePendingTree();
6721 host_impl_->sync_tree()->set_top_controls_height(0);
6722 host_impl_->ActivateSyncTree();
6723 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6725 host_impl_->CreatePendingTree();
6726 host_impl_->sync_tree()->set_top_controls_height(50);
6727 host_impl_->ActivateSyncTree();
6728 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6731 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6732 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6733 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6734 host_impl_->DidChangeTopControlsPosition();
6735 EXPECT_TRUE(did_request_animate_);
6736 EXPECT_TRUE(did_request_redraw_);
6739 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6740 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6741 host_impl_->SetViewportSize(gfx::Size(100, 100));
6742 host_impl_->top_controls_manager()->UpdateTopControlsState(
6743 BOTH, SHOWN, false);
6744 DrawFrame();
6746 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6747 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6748 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6749 EXPECT_EQ(gfx::Vector2dF().ToString(),
6750 scroll_layer->CurrentScrollOffset().ToString());
6752 // Scroll just the top controls and verify that the scroll succeeds.
6753 const float residue = 10;
6754 float offset = top_controls_height_ - residue;
6755 EXPECT_TRUE(
6756 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6757 EXPECT_FLOAT_EQ(-offset,
6758 host_impl_->top_controls_manager()->ControlsTopOffset());
6759 EXPECT_EQ(gfx::Vector2dF().ToString(),
6760 scroll_layer->CurrentScrollOffset().ToString());
6762 // Scroll across the boundary
6763 const float content_scroll = 20;
6764 offset = residue + content_scroll;
6765 EXPECT_TRUE(
6766 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6767 EXPECT_EQ(-top_controls_height_,
6768 host_impl_->top_controls_manager()->ControlsTopOffset());
6769 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6770 scroll_layer->CurrentScrollOffset().ToString());
6772 // Now scroll back to the top of the content
6773 offset = -content_scroll;
6774 EXPECT_TRUE(
6775 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6776 EXPECT_EQ(-top_controls_height_,
6777 host_impl_->top_controls_manager()->ControlsTopOffset());
6778 EXPECT_EQ(gfx::Vector2dF().ToString(),
6779 scroll_layer->CurrentScrollOffset().ToString());
6781 // And scroll the top controls completely into view
6782 offset = -top_controls_height_;
6783 EXPECT_TRUE(
6784 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6785 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6786 EXPECT_EQ(gfx::Vector2dF().ToString(),
6787 scroll_layer->CurrentScrollOffset().ToString());
6789 // And attempt to scroll past the end
6790 EXPECT_FALSE(
6791 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6792 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6793 EXPECT_EQ(gfx::Vector2dF().ToString(),
6794 scroll_layer->CurrentScrollOffset().ToString());
6796 host_impl_->ScrollEnd();
6799 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
6800 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6801 host_impl_->SetViewportSize(gfx::Size(100, 200));
6802 host_impl_->top_controls_manager()->UpdateTopControlsState(
6803 BOTH, SHOWN, false);
6804 DrawFrame();
6806 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6807 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6808 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6809 EXPECT_EQ(gfx::Vector2dF().ToString(),
6810 scroll_layer->CurrentScrollOffset().ToString());
6812 // Scroll the top controls partially.
6813 const float residue = 35;
6814 float offset = top_controls_height_ - residue;
6815 EXPECT_TRUE(
6816 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6817 EXPECT_FLOAT_EQ(-offset,
6818 host_impl_->top_controls_manager()->ControlsTopOffset());
6819 EXPECT_EQ(gfx::Vector2dF().ToString(),
6820 scroll_layer->CurrentScrollOffset().ToString());
6822 did_request_redraw_ = false;
6823 did_request_animate_ = false;
6824 did_request_commit_ = false;
6826 // End the scroll while the controls are still offset from their limit.
6827 host_impl_->ScrollEnd();
6828 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6829 EXPECT_TRUE(did_request_animate_);
6830 EXPECT_TRUE(did_request_redraw_);
6831 EXPECT_FALSE(did_request_commit_);
6833 // The top controls should properly animate until finished, despite the scroll
6834 // offset being at the origin.
6835 base::TimeTicks animation_time = gfx::FrameTime::Now();
6836 while (did_request_animate_) {
6837 did_request_redraw_ = false;
6838 did_request_animate_ = false;
6839 did_request_commit_ = false;
6841 float old_offset =
6842 host_impl_->top_controls_manager()->ControlsTopOffset();
6844 animation_time += base::TimeDelta::FromMilliseconds(5);
6845 host_impl_->Animate(animation_time);
6846 EXPECT_EQ(gfx::Vector2dF().ToString(),
6847 scroll_layer->CurrentScrollOffset().ToString());
6849 float new_offset =
6850 host_impl_->top_controls_manager()->ControlsTopOffset();
6852 // No commit is needed as the controls are animating the content offset,
6853 // not the scroll offset.
6854 EXPECT_FALSE(did_request_commit_);
6856 if (new_offset != old_offset)
6857 EXPECT_TRUE(did_request_redraw_);
6859 if (new_offset != 0) {
6860 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
6861 EXPECT_TRUE(did_request_animate_);
6864 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6867 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
6868 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6869 host_impl_->SetViewportSize(gfx::Size(100, 100));
6870 host_impl_->top_controls_manager()->UpdateTopControlsState(
6871 BOTH, SHOWN, false);
6872 float initial_scroll_offset = 50;
6873 scroll_layer->PushScrollOffsetFromMainThread(
6874 gfx::ScrollOffset(0, initial_scroll_offset));
6875 DrawFrame();
6877 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6878 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6879 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6880 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6881 scroll_layer->CurrentScrollOffset().ToString());
6883 // Scroll the top controls partially.
6884 const float residue = 15;
6885 float offset = top_controls_height_ - residue;
6886 EXPECT_TRUE(
6887 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6888 EXPECT_FLOAT_EQ(-offset,
6889 host_impl_->top_controls_manager()->ControlsTopOffset());
6890 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6891 scroll_layer->CurrentScrollOffset().ToString());
6893 did_request_redraw_ = false;
6894 did_request_animate_ = false;
6895 did_request_commit_ = false;
6897 // End the scroll while the controls are still offset from the limit.
6898 host_impl_->ScrollEnd();
6899 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6900 EXPECT_TRUE(did_request_animate_);
6901 EXPECT_TRUE(did_request_redraw_);
6902 EXPECT_FALSE(did_request_commit_);
6904 // Animate the top controls to the limit.
6905 base::TimeTicks animation_time = gfx::FrameTime::Now();
6906 while (did_request_animate_) {
6907 did_request_redraw_ = false;
6908 did_request_animate_ = false;
6909 did_request_commit_ = false;
6911 float old_offset =
6912 host_impl_->top_controls_manager()->ControlsTopOffset();
6914 animation_time += base::TimeDelta::FromMilliseconds(5);
6915 host_impl_->Animate(animation_time);
6917 float new_offset =
6918 host_impl_->top_controls_manager()->ControlsTopOffset();
6920 if (new_offset != old_offset) {
6921 EXPECT_TRUE(did_request_redraw_);
6922 EXPECT_TRUE(did_request_commit_);
6925 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6926 EXPECT_EQ(-top_controls_height_,
6927 host_impl_->top_controls_manager()->ControlsTopOffset());
6930 TEST_F(LayerTreeHostImplWithTopControlsTest,
6931 TopControlsAnimationAfterMainThreadFlingStopped) {
6932 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6933 host_impl_->SetViewportSize(gfx::Size(100, 100));
6934 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
6935 false);
6936 float initial_scroll_offset = 50;
6937 scroll_layer->PushScrollOffsetFromMainThread(
6938 gfx::ScrollOffset(0, initial_scroll_offset));
6939 DrawFrame();
6941 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6942 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6943 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6944 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6945 scroll_layer->CurrentScrollOffset().ToString());
6947 // Scroll the top controls partially.
6948 const float residue = 15;
6949 float offset = top_controls_height_ - residue;
6950 EXPECT_TRUE(
6951 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
6952 EXPECT_FLOAT_EQ(-offset,
6953 host_impl_->top_controls_manager()->ControlsTopOffset());
6954 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
6955 scroll_layer->CurrentScrollOffset().ToString());
6957 did_request_redraw_ = false;
6958 did_request_animate_ = false;
6959 did_request_commit_ = false;
6961 // End the fling while the controls are still offset from the limit.
6962 host_impl_->MainThreadHasStoppedFlinging();
6963 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
6964 EXPECT_TRUE(did_request_animate_);
6965 EXPECT_TRUE(did_request_redraw_);
6966 EXPECT_FALSE(did_request_commit_);
6968 // Animate the top controls to the limit.
6969 base::TimeTicks animation_time = gfx::FrameTime::Now();
6970 while (did_request_animate_) {
6971 did_request_redraw_ = false;
6972 did_request_animate_ = false;
6973 did_request_commit_ = false;
6975 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
6977 animation_time += base::TimeDelta::FromMilliseconds(5);
6978 host_impl_->Animate(animation_time);
6980 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
6982 if (new_offset != old_offset) {
6983 EXPECT_TRUE(did_request_redraw_);
6984 EXPECT_TRUE(did_request_commit_);
6987 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
6988 EXPECT_EQ(-top_controls_height_,
6989 host_impl_->top_controls_manager()->ControlsTopOffset());
6992 TEST_F(LayerTreeHostImplWithTopControlsTest,
6993 TopControlsScrollDeltaInOverScroll) {
6994 // test varifies that the overscroll delta should not have accumulated in
6995 // the top controls if we do a hide and show without releasing finger.
6997 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6998 host_impl_->SetViewportSize(gfx::Size(100, 100));
6999 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7000 false);
7001 DrawFrame();
7003 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7004 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7005 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7007 float offset = 50;
7008 EXPECT_TRUE(
7009 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7010 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7011 EXPECT_EQ(gfx::Vector2dF().ToString(),
7012 scroll_layer->CurrentScrollOffset().ToString());
7014 EXPECT_TRUE(
7015 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7016 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7017 scroll_layer->CurrentScrollOffset().ToString());
7019 EXPECT_TRUE(
7020 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7022 // Should have fully scrolled
7023 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7024 scroll_layer->CurrentScrollOffset().ToString());
7026 float overscrollamount = 10;
7028 // Overscroll the content
7029 EXPECT_FALSE(
7030 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7031 .did_scroll);
7032 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7033 scroll_layer->CurrentScrollOffset().ToString());
7034 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7035 host_impl_->accumulated_root_overscroll().ToString());
7037 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7038 .did_scroll);
7039 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7040 scroll_layer->CurrentScrollOffset().ToString());
7041 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7043 EXPECT_TRUE(
7044 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7045 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7046 scroll_layer->CurrentScrollOffset().ToString());
7048 // Top controls should be fully visible
7049 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7051 host_impl_->ScrollEnd();
7054 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7055 public:
7056 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7057 const gfx::Size& outer_viewport,
7058 const gfx::Size& inner_viewport) {
7059 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7060 const int kOuterViewportClipLayerId = 6;
7061 const int kOuterViewportScrollLayerId = 7;
7062 const int kInnerViewportScrollLayerId = 2;
7063 const int kInnerViewportClipLayerId = 4;
7064 const int kPageScaleLayerId = 5;
7066 scoped_ptr<LayerImpl> inner_scroll =
7067 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7068 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7069 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7071 scoped_ptr<LayerImpl> inner_clip =
7072 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7073 inner_clip->SetBounds(inner_viewport);
7075 scoped_ptr<LayerImpl> page_scale =
7076 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7078 inner_scroll->SetScrollClipLayer(inner_clip->id());
7079 inner_scroll->SetBounds(outer_viewport);
7080 inner_scroll->SetContentBounds(outer_viewport);
7081 inner_scroll->SetPosition(gfx::PointF());
7083 scoped_ptr<LayerImpl> outer_clip =
7084 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7085 outer_clip->SetBounds(outer_viewport);
7086 outer_clip->SetIsContainerForFixedPositionLayers(true);
7088 scoped_ptr<LayerImpl> outer_scroll =
7089 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7090 outer_scroll->SetScrollClipLayer(outer_clip->id());
7091 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7092 outer_scroll->SetBounds(content_size);
7093 outer_scroll->SetContentBounds(content_size);
7094 outer_scroll->SetPosition(gfx::PointF());
7096 scoped_ptr<LayerImpl> contents =
7097 LayerImpl::Create(layer_tree_impl, 8);
7098 contents->SetDrawsContent(true);
7099 contents->SetBounds(content_size);
7100 contents->SetContentBounds(content_size);
7101 contents->SetPosition(gfx::PointF());
7103 outer_scroll->AddChild(contents.Pass());
7104 outer_clip->AddChild(outer_scroll.Pass());
7105 inner_scroll->AddChild(outer_clip.Pass());
7106 page_scale->AddChild(inner_scroll.Pass());
7107 inner_clip->AddChild(page_scale.Pass());
7109 inner_clip->SetHasRenderSurface(true);
7110 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7111 layer_tree_impl->SetViewportLayersFromIds(
7112 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7113 kOuterViewportScrollLayerId);
7115 host_impl_->active_tree()->DidBecomeActive();
7119 TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
7120 gfx::Size content_size = gfx::Size(100, 160);
7121 gfx::Size outer_viewport = gfx::Size(50, 80);
7122 gfx::Size inner_viewport = gfx::Size(25, 40);
7124 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7126 TestScrollOffsetDelegate scroll_delegate;
7127 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
7129 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7130 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7131 DrawFrame();
7133 gfx::ScrollOffset inner_expected;
7134 gfx::ScrollOffset outer_expected;
7135 EXPECT_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7136 EXPECT_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7138 gfx::ScrollOffset current_offset(70.f, 100.f);
7140 scroll_delegate.set_getter_return_value(current_offset);
7141 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
7142 EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
7143 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
7145 // Outer viewport scrolls first. Then the rest is applied to the inner
7146 // viewport.
7147 EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f),
7148 inner_scroll->CurrentScrollOffset());
7149 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f),
7150 outer_scroll->CurrentScrollOffset());
7154 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7155 gfx::Size content_size = gfx::Size(100, 160);
7156 gfx::Size outer_viewport = gfx::Size(50, 80);
7157 gfx::Size inner_viewport = gfx::Size(25, 40);
7159 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7161 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7162 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7163 DrawFrame();
7165 gfx::Vector2dF inner_expected;
7166 gfx::Vector2dF outer_expected;
7167 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7168 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7170 // Make sure the fling goes to the outer viewport first
7171 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7172 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7173 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7175 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7176 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7177 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7179 host_impl_->ScrollEnd();
7181 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7182 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7184 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7185 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7186 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7187 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7189 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7190 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7192 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7193 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7195 host_impl_->ScrollEnd();
7197 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7198 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7202 TEST_F(LayerTreeHostImplVirtualViewportTest,
7203 DiagonalScrollBubblesPerfectlyToInner) {
7204 gfx::Size content_size = gfx::Size(100, 160);
7205 gfx::Size outer_viewport = gfx::Size(50, 80);
7206 gfx::Size inner_viewport = gfx::Size(25, 40);
7208 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7210 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7211 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7212 DrawFrame();
7214 gfx::Vector2dF inner_expected;
7215 gfx::Vector2dF outer_expected;
7216 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7217 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7219 // Make sure the scroll goes to the outer viewport first.
7220 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7221 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7222 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7224 // Scroll near the edge of the outer viewport.
7225 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7226 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7227 outer_expected += scroll_delta;
7229 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7230 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7232 // Now diagonal scroll across the outer viewport boundary in a single event.
7233 // The entirety of the scroll should be consumed, as bubbling between inner
7234 // and outer viewport layers is perfect.
7235 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7236 outer_expected += scroll_delta;
7237 inner_expected += scroll_delta;
7238 host_impl_->ScrollEnd();
7240 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7241 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7245 TEST_F(LayerTreeHostImplVirtualViewportTest,
7246 TouchFlingCanLockToViewportLayerAfterBubbling) {
7247 gfx::Size content_size = gfx::Size(100, 160);
7248 gfx::Size outer_viewport = gfx::Size(50, 80);
7249 gfx::Size inner_viewport = gfx::Size(25, 40);
7251 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7253 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7254 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7256 scoped_ptr<LayerImpl> child =
7257 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7258 LayerImpl* child_scroll = child.get();
7259 outer_scroll->children()[0]->AddChild(child.Pass());
7261 DrawFrame();
7263 scoped_ptr<ScrollAndScaleSet> scroll_info;
7265 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7266 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7267 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7268 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7270 // The child should have scrolled up to its limit.
7271 scroll_info = host_impl_->ProcessScrollDeltas();
7272 ASSERT_EQ(1u, scroll_info->scrolls.size());
7273 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
7274 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7276 // The first |ScrollBy| after the fling should re-lock the scrolling
7277 // layer to the first layer that scrolled, the inner viewport scroll layer.
7278 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7279 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7280 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7282 // The inner viewport should have scrolled up to its limit.
7283 scroll_info = host_impl_->ProcessScrollDeltas();
7284 ASSERT_EQ(2u, scroll_info->scrolls.size());
7285 ExpectContains(*scroll_info, child_scroll->id(), scroll_delta);
7286 ExpectContains(*scroll_info, inner_scroll->id(), scroll_delta);
7288 // As the locked layer is at its limit, no further scrolling can occur.
7289 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7290 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7291 host_impl_->ScrollEnd();
7295 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7296 public:
7297 void SetUp() override {
7298 LayerTreeSettings settings = DefaultSettings();
7299 settings.max_memory_for_prepaint_percentage = 50;
7300 CreateHostImpl(settings, CreateOutputSurface());
7304 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7305 // Set up a memory policy and percentages which could cause
7306 // 32-bit integer overflows.
7307 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7309 // Verify implicit limits are calculated correctly with no overflows
7310 host_impl_->SetMemoryPolicy(mem_policy);
7311 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7312 300u * 1024u * 1024u);
7313 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7314 150u * 1024u * 1024u);
7317 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7318 const gfx::Size layer_size(100, 100);
7319 gfx::Transform external_transform;
7320 const gfx::Rect external_viewport(layer_size);
7321 const gfx::Rect external_clip(layer_size);
7322 const bool resourceless_software_draw = false;
7323 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7325 host_impl_->SetExternalDrawConstraints(external_transform,
7326 external_viewport,
7327 external_clip,
7328 external_viewport,
7329 external_transform,
7330 resourceless_software_draw);
7331 DrawFrame();
7332 EXPECT_TRANSFORMATION_MATRIX_EQ(
7333 external_transform, layer->draw_properties().target_space_transform);
7335 external_transform.Translate(20, 20);
7336 host_impl_->SetExternalDrawConstraints(external_transform,
7337 external_viewport,
7338 external_clip,
7339 external_viewport,
7340 external_transform,
7341 resourceless_software_draw);
7342 DrawFrame();
7343 EXPECT_TRANSFORMATION_MATRIX_EQ(
7344 external_transform, layer->draw_properties().target_space_transform);
7347 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
7348 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7349 DrawFrame();
7351 base::TimeTicks start_time =
7352 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7354 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7355 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7357 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7359 host_impl_->Animate(start_time);
7360 host_impl_->UpdateAnimationState(true);
7362 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
7364 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7365 host_impl_->UpdateAnimationState(true);
7367 float y = scrolling_layer->CurrentScrollOffset().y();
7368 EXPECT_TRUE(y > 1 && y < 49);
7370 // Update target.
7371 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7372 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7374 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7375 host_impl_->UpdateAnimationState(true);
7377 y = scrolling_layer->CurrentScrollOffset().y();
7378 EXPECT_TRUE(y > 50 && y < 100);
7379 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7381 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7382 host_impl_->UpdateAnimationState(true);
7384 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7385 scrolling_layer->CurrentScrollOffset());
7386 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7389 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairs) {
7390 host_impl_->CreatePendingTree();
7392 scoped_ptr<PictureLayerImpl> layer =
7393 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
7394 layer->SetBounds(gfx::Size(10, 10));
7395 scoped_ptr<FakePictureLayerImpl> nondraw_layer =
7396 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
7397 nondraw_layer->SetBounds(gfx::Size(10, 10));
7399 scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
7400 gfx::Size(10, 10), gfx::Size(10, 10)));
7401 Region empty_invalidation;
7402 const PictureLayerTilingSet* null_tiling_set = nullptr;
7403 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
7404 layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
7405 nondraw_layer->set_gpu_raster_max_texture_size(
7406 host_impl_->device_viewport_size());
7407 nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
7409 layer->AddChild(nondraw_layer.Pass());
7410 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
7412 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7413 LayerImpl* pending_layer = pending_tree->root_layer();
7414 FakePictureLayerImpl* pending_nondraw_layer =
7415 static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
7417 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
7419 std::vector<PictureLayerImpl::Pair> layer_pairs;
7420 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7421 EXPECT_EQ(1u, layer_pairs.size());
7422 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7423 EXPECT_EQ(nullptr, layer_pairs[0].active);
7425 host_impl_->ActivateSyncTree();
7427 LayerTreeImpl* active_tree = host_impl_->active_tree();
7428 LayerImpl* active_layer = active_tree->root_layer();
7429 FakePictureLayerImpl* active_nondraw_layer =
7430 static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
7431 EXPECT_NE(active_tree, pending_tree);
7432 EXPECT_NE(active_layer, pending_layer);
7433 EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
7434 EXPECT_NE(nullptr, active_tree);
7435 EXPECT_NE(nullptr, active_layer);
7436 EXPECT_NE(nullptr, active_nondraw_layer);
7438 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
7440 host_impl_->CreatePendingTree();
7442 layer_pairs.clear();
7443 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7444 EXPECT_EQ(1u, layer_pairs.size());
7445 EXPECT_EQ(active_layer, layer_pairs[0].active);
7446 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7448 // Activate, the active layer has no twin now.
7449 host_impl_->ActivateSyncTree();
7451 layer_pairs.clear();
7452 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7453 EXPECT_EQ(1u, layer_pairs.size());
7454 EXPECT_EQ(active_layer, layer_pairs[0].active);
7455 EXPECT_EQ(nullptr, layer_pairs[0].pending);
7457 // Create another layer in the pending tree that's not in the active tree. We
7458 // should get two pairs.
7459 host_impl_->CreatePendingTree();
7460 host_impl_->pending_tree()->root_layer()->AddChild(
7461 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
7463 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
7465 layer_pairs.clear();
7466 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7467 EXPECT_EQ(2u, layer_pairs.size());
7468 // The pair ordering is flaky, so make it consistent.
7469 if (layer_pairs[0].active != active_layer)
7470 std::swap(layer_pairs[0], layer_pairs[1]);
7471 EXPECT_EQ(active_layer, layer_pairs[0].active);
7472 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7473 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
7474 EXPECT_EQ(nullptr, layer_pairs[1].active);
7476 host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
7478 // Have the pending layer be part of the RSLL now. It should appear in the
7479 // list without an active twin.
7480 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
7482 layer_pairs.clear();
7483 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7484 EXPECT_EQ(2u, layer_pairs.size());
7485 // The pair ordering is flaky, so make it consistent.
7486 if (layer_pairs[0].active != active_layer)
7487 std::swap(layer_pairs[0], layer_pairs[1]);
7488 EXPECT_EQ(active_layer, layer_pairs[0].active);
7489 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7490 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
7491 EXPECT_EQ(nullptr, layer_pairs[1].active);
7493 // Have the active layer be part of the RSLL now instead. It should appear in
7494 // the list without a pending twin.
7495 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
7496 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
7498 layer_pairs.clear();
7499 host_impl_->GetPictureLayerImplPairs(&layer_pairs, true);
7500 EXPECT_EQ(2u, layer_pairs.size());
7501 // The pair ordering is flaky, so make it consistent.
7502 if (layer_pairs[0].active != active_layer)
7503 std::swap(layer_pairs[0], layer_pairs[1]);
7504 EXPECT_EQ(active_layer, layer_pairs[0].active);
7505 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7506 EXPECT_EQ(nullptr, layer_pairs[1].pending);
7507 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
7510 TEST_F(LayerTreeHostImplTest, GetPictureLayerImplPairsWithNonRSLLMembers) {
7511 host_impl_->CreatePendingTree();
7513 scoped_ptr<PictureLayerImpl> layer =
7514 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 10);
7515 layer->SetBounds(gfx::Size(10, 10));
7516 scoped_ptr<FakePictureLayerImpl> nondraw_layer =
7517 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 12);
7518 nondraw_layer->SetBounds(gfx::Size(10, 10));
7520 scoped_refptr<RasterSource> pile(FakePicturePileImpl::CreateEmptyPile(
7521 gfx::Size(10, 10), gfx::Size(10, 10)));
7522 Region empty_invalidation;
7523 const PictureLayerTilingSet* null_tiling_set = nullptr;
7524 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
7525 layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
7526 nondraw_layer->set_gpu_raster_max_texture_size(
7527 host_impl_->device_viewport_size());
7528 nondraw_layer->UpdateRasterSource(pile, &empty_invalidation, null_tiling_set);
7530 layer->AddChild(nondraw_layer.Pass());
7531 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
7533 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7534 LayerImpl* pending_layer = pending_tree->root_layer();
7535 FakePictureLayerImpl* pending_nondraw_layer =
7536 static_cast<FakePictureLayerImpl*>(pending_layer->children()[0]);
7538 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
7540 std::vector<PictureLayerImpl::Pair> layer_pairs;
7541 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
7542 EXPECT_EQ(2u, layer_pairs.size());
7543 // The pair ordering is flaky, so make it consistent.
7544 if (layer_pairs[0].pending != pending_layer)
7545 std::swap(layer_pairs[0], layer_pairs[1]);
7546 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7547 EXPECT_EQ(nullptr, layer_pairs[0].active);
7548 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
7549 EXPECT_EQ(nullptr, layer_pairs[1].active);
7551 host_impl_->ActivateSyncTree();
7553 LayerTreeImpl* active_tree = host_impl_->active_tree();
7554 LayerImpl* active_layer = active_tree->root_layer();
7555 FakePictureLayerImpl* active_nondraw_layer =
7556 static_cast<FakePictureLayerImpl*>(active_layer->children()[0]);
7557 EXPECT_NE(active_tree, pending_tree);
7558 EXPECT_NE(active_layer, pending_layer);
7559 EXPECT_NE(active_nondraw_layer, pending_nondraw_layer);
7560 EXPECT_NE(nullptr, active_tree);
7561 EXPECT_NE(nullptr, active_layer);
7562 EXPECT_NE(nullptr, active_nondraw_layer);
7564 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
7566 host_impl_->CreatePendingTree();
7568 layer_pairs.clear();
7569 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
7570 EXPECT_EQ(2u, layer_pairs.size());
7571 // The pair ordering is flaky, so make it consistent.
7572 if (layer_pairs[0].active != active_layer)
7573 std::swap(layer_pairs[0], layer_pairs[1]);
7574 EXPECT_EQ(active_layer, layer_pairs[0].active);
7575 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7576 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
7577 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
7579 // Activate, the active layer has no twin now.
7580 host_impl_->ActivateSyncTree();
7582 layer_pairs.clear();
7583 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
7584 EXPECT_EQ(2u, layer_pairs.size());
7585 // The pair ordering is flaky, so make it consistent.
7586 if (layer_pairs[0].active != active_layer)
7587 std::swap(layer_pairs[0], layer_pairs[1]);
7588 EXPECT_EQ(active_layer, layer_pairs[0].active);
7589 EXPECT_EQ(nullptr, layer_pairs[0].pending);
7590 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
7591 EXPECT_EQ(nullptr, layer_pairs[1].pending);
7593 // Create another layer in the pending tree that's not in the active tree. We
7594 // should get three pairs including the nondraw layers.
7595 host_impl_->CreatePendingTree();
7596 host_impl_->pending_tree()->root_layer()->AddChild(
7597 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11));
7599 LayerImpl* new_pending_layer = pending_tree->root_layer()->children()[1];
7601 layer_pairs.clear();
7602 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
7603 EXPECT_EQ(3u, layer_pairs.size());
7604 // The pair ordering is flaky, so make it consistent.
7605 if (layer_pairs[0].active != active_layer)
7606 std::swap(layer_pairs[0], layer_pairs[1]);
7607 if (layer_pairs[0].active != active_layer)
7608 std::swap(layer_pairs[0], layer_pairs[2]);
7609 if (layer_pairs[1].pending != new_pending_layer)
7610 std::swap(layer_pairs[1], layer_pairs[2]);
7611 EXPECT_EQ(active_layer, layer_pairs[0].active);
7612 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7613 EXPECT_EQ(new_pending_layer, layer_pairs[1].pending);
7614 EXPECT_EQ(nullptr, layer_pairs[1].active);
7615 EXPECT_EQ(active_nondraw_layer, layer_pairs[2].active);
7616 EXPECT_EQ(pending_nondraw_layer, layer_pairs[2].pending);
7618 host_impl_->pending_tree()->root_layer()->RemoveChild(new_pending_layer);
7620 // Have the pending layer be part of the RSLL now. It should appear in the
7621 // list, as should its active twin since we don't request only layers with
7622 // valid draw properties.
7623 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
7625 layer_pairs.clear();
7626 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
7627 EXPECT_EQ(2u, layer_pairs.size());
7628 // The pair ordering is flaky, so make it consistent.
7629 if (layer_pairs[0].active != active_layer)
7630 std::swap(layer_pairs[0], layer_pairs[1]);
7631 EXPECT_EQ(active_layer, layer_pairs[0].active);
7632 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7633 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
7634 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
7636 // Have the active layer be part of the RSLL now instead. It should appear in
7637 // the list, as should its pending twin since we don't request only layers
7638 // with valid draw properties.
7639 pending_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(false);
7640 active_nondraw_layer->SetIsDrawnRenderSurfaceLayerListMember(true);
7642 layer_pairs.clear();
7643 host_impl_->GetPictureLayerImplPairs(&layer_pairs, false);
7644 EXPECT_EQ(2u, layer_pairs.size());
7645 // The pair ordering is flaky, so make it consistent.
7646 if (layer_pairs[0].active != active_layer)
7647 std::swap(layer_pairs[0], layer_pairs[1]);
7648 EXPECT_EQ(active_layer, layer_pairs[0].active);
7649 EXPECT_EQ(pending_layer, layer_pairs[0].pending);
7650 EXPECT_EQ(active_nondraw_layer, layer_pairs[1].active);
7651 EXPECT_EQ(pending_nondraw_layer, layer_pairs[1].pending);
7654 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
7655 host_impl_->CreatePendingTree();
7656 host_impl_->ActivateSyncTree();
7657 host_impl_->CreatePendingTree();
7659 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7661 scoped_ptr<FakePictureLayerImpl> pending_layer =
7662 FakePictureLayerImpl::Create(pending_tree, 10);
7663 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
7664 pending_tree->SetRootLayer(pending_layer.Pass());
7665 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
7667 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
7668 pending_tree->DidBecomeActive();
7669 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7671 scoped_ptr<FakePictureLayerImpl> mask_layer =
7672 FakePictureLayerImpl::Create(pending_tree, 11);
7673 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
7674 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
7675 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
7677 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7678 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
7679 pending_tree->DidBecomeActive();
7680 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7681 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7683 scoped_ptr<FakePictureLayerImpl> replica_layer =
7684 FakePictureLayerImpl::Create(pending_tree, 12);
7685 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
7686 FakePictureLayerImpl::Create(pending_tree, 13);
7687 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
7688 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
7689 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
7690 ASSERT_EQ(raw_replica_mask_layer,
7691 raw_pending_layer->replica_layer()->mask_layer());
7693 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7694 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7695 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
7696 pending_tree->DidBecomeActive();
7697 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
7698 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
7699 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
7702 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
7703 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7704 host_impl_->SetViewportSize(gfx::Size(50, 50));
7705 DrawFrame();
7707 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
7709 float min_page_scale = 1.f, max_page_scale = 4.f;
7710 float page_scale_factor = 1.f;
7712 // The scroll deltas should have the page scale factor applied.
7714 host_impl_->active_tree()->PushPageScaleFromMainThread(
7715 page_scale_factor, min_page_scale, max_page_scale);
7716 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
7717 scroll_layer->SetScrollDelta(gfx::Vector2d());
7719 float page_scale_delta = 2.f;
7720 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
7721 host_impl_->PinchGestureBegin();
7722 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
7723 host_impl_->PinchGestureEnd();
7724 host_impl_->ScrollEnd();
7726 gfx::Vector2dF scroll_delta(0, 5);
7727 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7728 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7729 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
7731 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7732 host_impl_->ScrollEnd();
7733 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7734 scroll_layer->CurrentScrollOffset());
7738 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
7739 public:
7740 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7741 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
7743 protected:
7744 int num_lost_surfaces_;
7747 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
7748 // Really we just need at least one client notification each time
7749 // we go from having a valid output surface to not having a valid output
7750 // surface.
7751 EXPECT_EQ(0, num_lost_surfaces_);
7752 host_impl_->DidLoseOutputSurface();
7753 EXPECT_EQ(1, num_lost_surfaces_);
7754 host_impl_->DidLoseOutputSurface();
7755 EXPECT_LE(1, num_lost_surfaces_);
7758 TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) {
7759 LayerTreeHostImpl::FrameData frame;
7760 frame.render_passes.push_back(RenderPass::Create());
7761 RenderPass* pass3 = frame.render_passes.back();
7762 frame.render_passes.push_back(RenderPass::Create());
7763 RenderPass* pass2 = frame.render_passes.back();
7764 frame.render_passes.push_back(RenderPass::Create());
7765 RenderPass* pass1 = frame.render_passes.back();
7767 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7768 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7769 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7771 frame.render_passes_by_id[pass1->id] = pass1;
7772 frame.render_passes_by_id[pass2->id] = pass2;
7773 frame.render_passes_by_id[pass3->id] = pass3;
7775 // Add a quad to each pass so they aren't empty.
7776 SolidColorDrawQuad* color_quad;
7777 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7778 color_quad->material = DrawQuad::SOLID_COLOR;
7779 color_quad = pass2->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7780 color_quad->material = DrawQuad::SOLID_COLOR;
7781 color_quad = pass3->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7782 color_quad->material = DrawQuad::SOLID_COLOR;
7784 // pass3 is referenced by pass2.
7785 RenderPassDrawQuad* rpdq =
7786 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7787 rpdq->material = DrawQuad::RENDER_PASS;
7788 rpdq->render_pass_id = pass3->id;
7790 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7791 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7792 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7793 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7794 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7795 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7796 EXPECT_EQ(1u, frame.render_passes.size());
7797 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7800 TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) {
7801 LayerTreeHostImpl::FrameData frame;
7802 frame.render_passes.push_back(RenderPass::Create());
7803 RenderPass* pass3 = frame.render_passes.back();
7804 frame.render_passes.push_back(RenderPass::Create());
7805 RenderPass* pass2 = frame.render_passes.back();
7806 frame.render_passes.push_back(RenderPass::Create());
7807 RenderPass* pass1 = frame.render_passes.back();
7809 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7810 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7811 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7813 frame.render_passes_by_id[pass1->id] = pass1;
7814 frame.render_passes_by_id[pass2->id] = pass2;
7815 frame.render_passes_by_id[pass3->id] = pass3;
7817 // pass1 is not empty, but pass2 and pass3 are.
7818 SolidColorDrawQuad* color_quad;
7819 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7820 color_quad->material = DrawQuad::SOLID_COLOR;
7822 // pass3 is referenced by pass2.
7823 RenderPassDrawQuad* rpdq =
7824 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7825 rpdq->material = DrawQuad::RENDER_PASS;
7826 rpdq->render_pass_id = pass3->id;
7828 // pass2 is referenced by pass1.
7829 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7830 rpdq->material = DrawQuad::RENDER_PASS;
7831 rpdq->render_pass_id = pass2->id;
7833 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7834 // should be removed.
7835 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7836 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7837 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7838 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7839 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7840 EXPECT_EQ(1u, frame.render_passes.size());
7841 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7842 // The RenderPassDrawQuad should be removed from pass1.
7843 EXPECT_EQ(1u, pass1->quad_list.size());
7844 EXPECT_EQ(DrawQuad::SOLID_COLOR, pass1->quad_list.ElementAt(0)->material);
7847 TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) {
7848 LayerTreeHostImpl::FrameData frame;
7849 frame.render_passes.push_back(RenderPass::Create());
7850 RenderPass* pass3 = frame.render_passes.back();
7851 frame.render_passes.push_back(RenderPass::Create());
7852 RenderPass* pass2 = frame.render_passes.back();
7853 frame.render_passes.push_back(RenderPass::Create());
7854 RenderPass* pass1 = frame.render_passes.back();
7856 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7857 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7858 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7860 frame.render_passes_by_id[pass1->id] = pass1;
7861 frame.render_passes_by_id[pass2->id] = pass2;
7862 frame.render_passes_by_id[pass3->id] = pass3;
7864 // pass3 is referenced by pass2.
7865 RenderPassDrawQuad* rpdq =
7866 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7867 rpdq->material = DrawQuad::RENDER_PASS;
7868 rpdq->render_pass_id = pass3->id;
7870 // pass2 is referenced by pass1.
7871 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7872 rpdq->material = DrawQuad::RENDER_PASS;
7873 rpdq->render_pass_id = pass2->id;
7875 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7876 // should be removed. Then pass1 is empty too, but it's the root so it should
7877 // not be removed.
7878 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7879 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7880 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7881 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7882 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7883 EXPECT_EQ(1u, frame.render_passes.size());
7884 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7885 // The RenderPassDrawQuad should be removed from pass1.
7886 EXPECT_EQ(0u, pass1->quad_list.size());
7889 } // namespace
7890 } // namespace cc