Improve test coverage of unused scroll delta for cc scrolling.
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blob9e9d7367f74f559486007169d5c8ba4fb0bf4871
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/video_layer_impl.h"
31 #include "cc/layers/viewport.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/test/animation_test_common.h"
44 #include "cc/test/begin_frame_args_test.h"
45 #include "cc/test/fake_layer_tree_host_impl.h"
46 #include "cc/test/fake_output_surface.h"
47 #include "cc/test/fake_output_surface_client.h"
48 #include "cc/test/fake_picture_layer_impl.h"
49 #include "cc/test/fake_picture_pile_impl.h"
50 #include "cc/test/fake_proxy.h"
51 #include "cc/test/fake_video_frame_provider.h"
52 #include "cc/test/geometry_test_utils.h"
53 #include "cc/test/gpu_rasterization_enabled_settings.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/geometry/rect_conversions.h"
68 #include "ui/gfx/geometry/size_conversions.h"
69 #include "ui/gfx/geometry/vector2d_conversions.h"
71 using ::testing::Mock;
72 using ::testing::Return;
73 using ::testing::AnyNumber;
74 using ::testing::AtLeast;
75 using ::testing::_;
76 using media::VideoFrame;
78 namespace cc {
79 namespace {
81 class LayerTreeHostImplTest : public testing::Test,
82 public LayerTreeHostImplClient {
83 public:
84 LayerTreeHostImplTest()
85 : proxy_(base::ThreadTaskRunnerHandle::Get(),
86 base::ThreadTaskRunnerHandle::Get()),
87 always_impl_thread_(&proxy_),
88 always_main_thread_blocked_(&proxy_),
89 on_can_draw_state_changed_called_(false),
90 did_notify_ready_to_activate_(false),
91 did_request_commit_(false),
92 did_request_redraw_(false),
93 did_request_animate_(false),
94 did_request_prepare_tiles_(false),
95 did_complete_page_scale_animation_(false),
96 reduce_memory_result_(true) {
97 media::InitializeMediaLibrary();
100 LayerTreeSettings DefaultSettings() {
101 LayerTreeSettings settings;
102 settings.minimum_occlusion_tracking_size = gfx::Size();
103 settings.renderer_settings.texture_id_allocation_chunk_size = 1;
104 settings.report_overscroll_only_for_scrollable_axes = true;
105 settings.gpu_rasterization_enabled = true;
106 return settings;
109 void SetUp() override {
110 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
113 void TearDown() override {}
115 void UpdateRendererCapabilitiesOnImplThread() override {}
116 void DidLoseOutputSurfaceOnImplThread() override {}
117 void CommitVSyncParameters(base::TimeTicks timebase,
118 base::TimeDelta interval) override {}
119 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
120 void SetMaxSwapsPendingOnImplThread(int max) override {}
121 void DidSwapBuffersOnImplThread() override {}
122 void DidSwapBuffersCompleteOnImplThread() override {}
123 void OnCanDrawStateChanged(bool can_draw) override {
124 on_can_draw_state_changed_called_ = true;
126 void NotifyReadyToActivate() override {
127 did_notify_ready_to_activate_ = true;
128 host_impl_->ActivateSyncTree();
130 void NotifyReadyToDraw() override {}
131 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
132 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
133 did_request_redraw_ = true;
135 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
136 void SetNeedsPrepareTilesOnImplThread() override {
137 did_request_prepare_tiles_ = true;
139 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
140 void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
141 void PostAnimationEventsToMainThreadOnImplThread(
142 scoped_ptr<AnimationEventsVector> events) override {}
143 bool IsInsideDraw() override { return false; }
144 void RenewTreePriority() override {}
145 void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
146 base::TimeDelta delay) override {
147 animation_task_ = task;
148 requested_animation_delay_ = delay;
150 void DidActivateSyncTree() override {}
151 void WillPrepareTiles() override {}
152 void DidPrepareTiles() override {}
153 void DidCompletePageScaleAnimationOnImplThread() override {
154 did_complete_page_scale_animation_ = true;
156 void OnDrawForOutputSurface() override {}
157 void PostFrameTimingEventsOnImplThread(
158 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
159 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
160 override {}
162 void set_reduce_memory_result(bool reduce_memory_result) {
163 reduce_memory_result_ = reduce_memory_result;
166 virtual bool CreateHostImpl(const LayerTreeSettings& settings,
167 scoped_ptr<OutputSurface> output_surface) {
168 host_impl_ = LayerTreeHostImpl::Create(
169 settings, this, &proxy_, &stats_instrumentation_,
170 &shared_bitmap_manager_, &gpu_memory_buffer_manager_,
171 &task_graph_runner_, 0);
172 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
173 host_impl_->SetViewportSize(gfx::Size(10, 10));
174 // Set the BeginFrameArgs so that methods which use it are able to.
175 host_impl_->WillBeginImplFrame(
176 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
177 return init;
180 void SetupRootLayerImpl(scoped_ptr<LayerImpl> root) {
181 root->SetPosition(gfx::PointF());
182 root->SetBounds(gfx::Size(10, 10));
183 root->SetDrawsContent(true);
184 root->draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10);
185 root->SetHasRenderSurface(true);
186 host_impl_->active_tree()->SetRootLayer(root.Pass());
189 static void ExpectClearedScrollDeltasRecursive(LayerImpl* layer) {
190 ASSERT_EQ(layer->ScrollDelta(), gfx::Vector2d());
191 for (size_t i = 0; i < layer->children().size(); ++i)
192 ExpectClearedScrollDeltasRecursive(layer->children()[i]);
195 static ::testing::AssertionResult ScrollInfoContains(
196 const ScrollAndScaleSet& scroll_info,
197 int id,
198 const gfx::Vector2d& scroll_delta) {
199 int times_encountered = 0;
201 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
202 if (scroll_info.scrolls[i].layer_id != id)
203 continue;
205 if (scroll_delta != scroll_info.scrolls[i].scroll_delta) {
206 return ::testing::AssertionFailure()
207 << "Expected " << scroll_delta.ToString() << ", not "
208 << scroll_info.scrolls[i].scroll_delta.ToString();
210 times_encountered++;
213 if (times_encountered != 1)
214 return ::testing::AssertionFailure() << "No layer found with id " << id;
215 return ::testing::AssertionSuccess();
218 static void ExpectNone(const ScrollAndScaleSet& scroll_info, int id) {
219 int times_encountered = 0;
221 for (size_t i = 0; i < scroll_info.scrolls.size(); ++i) {
222 if (scroll_info.scrolls[i].layer_id != id)
223 continue;
224 times_encountered++;
227 ASSERT_EQ(0, times_encountered);
230 LayerImpl* CreateScrollAndContentsLayers(LayerTreeImpl* layer_tree_impl,
231 const gfx::Size& content_size) {
232 // Create both an inner viewport scroll layer and an outer viewport scroll
233 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
234 // 0x0, so the scrolls will be applied directly to the inner viewport.
235 const int kOuterViewportClipLayerId = 116;
236 const int kOuterViewportScrollLayerId = 117;
237 const int kContentLayerId = 118;
238 const int kInnerViewportScrollLayerId = 2;
239 const int kInnerViewportClipLayerId = 4;
240 const int kPageScaleLayerId = 5;
242 scoped_ptr<LayerImpl> root =
243 LayerImpl::Create(layer_tree_impl, 1);
244 root->SetBounds(content_size);
245 root->SetPosition(gfx::PointF());
246 root->SetHasRenderSurface(true);
248 scoped_ptr<LayerImpl> inner_scroll =
249 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
250 inner_scroll->SetIsContainerForFixedPositionLayers(true);
251 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
253 scoped_ptr<LayerImpl> inner_clip =
254 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
255 inner_clip->SetBounds(
256 gfx::Size(content_size.width() / 2, content_size.height() / 2));
258 scoped_ptr<LayerImpl> page_scale =
259 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
261 inner_scroll->SetScrollClipLayer(inner_clip->id());
262 inner_scroll->SetBounds(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->SetPosition(gfx::PointF());
277 scoped_ptr<LayerImpl> contents =
278 LayerImpl::Create(layer_tree_impl, kContentLayerId);
279 contents->SetDrawsContent(true);
280 contents->SetBounds(content_size);
281 contents->SetPosition(gfx::PointF());
283 outer_scroll->AddChild(contents.Pass());
284 outer_clip->AddChild(outer_scroll.Pass());
285 inner_scroll->AddChild(outer_clip.Pass());
286 page_scale->AddChild(inner_scroll.Pass());
287 inner_clip->AddChild(page_scale.Pass());
288 root->AddChild(inner_clip.Pass());
290 layer_tree_impl->SetRootLayer(root.Pass());
291 layer_tree_impl->SetViewportLayersFromIds(
292 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
293 kOuterViewportScrollLayerId);
295 layer_tree_impl->DidBecomeActive();
296 return layer_tree_impl->InnerViewportScrollLayer();
299 LayerImpl* SetupScrollAndContentsLayers(const gfx::Size& content_size) {
300 LayerImpl* scroll_layer = CreateScrollAndContentsLayers(
301 host_impl_->active_tree(), content_size);
302 host_impl_->active_tree()->DidBecomeActive();
303 return scroll_layer;
306 // Sets up a typical virtual viewport setup with one child content layer.
307 // Returns a pointer to the content layer.
308 LayerImpl* CreateBasicVirtualViewportLayers(const gfx::Size& viewport_size,
309 const gfx::Size& content_size) {
310 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
311 // the inner a different size from the outer. We'll reuse its layer
312 // hierarchy but adjust the sizing to our needs.
313 CreateScrollAndContentsLayers(host_impl_->active_tree(), content_size);
315 LayerImpl* content_layer =
316 host_impl_->OuterViewportScrollLayer()->children().back();
317 content_layer->SetBounds(content_size);
318 host_impl_->OuterViewportScrollLayer()->SetBounds(content_size);
320 LayerImpl* outer_clip = host_impl_->OuterViewportScrollLayer()->parent();
321 outer_clip->SetBounds(viewport_size);
323 LayerImpl* inner_clip_layer =
324 host_impl_->InnerViewportScrollLayer()->parent()->parent();
325 inner_clip_layer->SetBounds(viewport_size);
326 host_impl_->InnerViewportScrollLayer()->SetBounds(viewport_size);
328 host_impl_->SetViewportSize(viewport_size);
329 host_impl_->active_tree()->DidBecomeActive();
331 return content_layer;
334 // TODO(wjmaclean) Add clip-layer pointer to parameters.
335 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
336 const gfx::Size& size,
337 LayerImpl* clip_layer) {
338 DCHECK(clip_layer);
339 DCHECK(id != clip_layer->id());
340 scoped_ptr<LayerImpl> layer =
341 LayerImpl::Create(host_impl_->active_tree(), id);
342 layer->SetScrollClipLayer(clip_layer->id());
343 layer->SetDrawsContent(true);
344 layer->SetBounds(size);
345 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
346 return layer.Pass();
349 void DrawFrame() {
350 LayerTreeHostImpl::FrameData frame;
351 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
352 host_impl_->DrawLayers(&frame);
353 host_impl_->DidDrawAllLayers(frame);
356 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
357 void pinch_zoom_pan_viewport_test(float device_scale_factor);
358 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
359 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
360 float device_scale_factor);
362 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
363 // Note: It is not possible to disable the renderer once it has been set,
364 // so we do not need to test that disabling the renderer notifies us
365 // that can_draw changed.
366 EXPECT_FALSE(host_impl_->CanDraw());
367 on_can_draw_state_changed_called_ = false;
369 // Set up the root layer, which allows us to draw.
370 SetupScrollAndContentsLayers(gfx::Size(100, 100));
371 EXPECT_TRUE(host_impl_->CanDraw());
372 EXPECT_TRUE(on_can_draw_state_changed_called_);
373 on_can_draw_state_changed_called_ = false;
375 // Toggle the root layer to make sure it toggles can_draw
376 host_impl_->active_tree()->SetRootLayer(nullptr);
377 EXPECT_FALSE(host_impl_->CanDraw());
378 EXPECT_TRUE(on_can_draw_state_changed_called_);
379 on_can_draw_state_changed_called_ = false;
381 SetupScrollAndContentsLayers(gfx::Size(100, 100));
382 EXPECT_TRUE(host_impl_->CanDraw());
383 EXPECT_TRUE(on_can_draw_state_changed_called_);
384 on_can_draw_state_changed_called_ = false;
386 // Toggle the device viewport size to make sure it toggles can_draw.
387 host_impl_->SetViewportSize(gfx::Size());
388 if (always_draw) {
389 EXPECT_TRUE(host_impl_->CanDraw());
390 } else {
391 EXPECT_FALSE(host_impl_->CanDraw());
393 EXPECT_TRUE(on_can_draw_state_changed_called_);
394 on_can_draw_state_changed_called_ = false;
396 host_impl_->SetViewportSize(gfx::Size(100, 100));
397 EXPECT_TRUE(host_impl_->CanDraw());
398 EXPECT_TRUE(on_can_draw_state_changed_called_);
399 on_can_draw_state_changed_called_ = false;
402 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
404 protected:
405 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
406 return FakeOutputSurface::Create3d();
409 void DrawOneFrame() {
410 LayerTreeHostImpl::FrameData frame_data;
411 host_impl_->PrepareToDraw(&frame_data);
412 host_impl_->DidDrawAllLayers(frame_data);
415 FakeProxy proxy_;
416 DebugScopedSetImplThread always_impl_thread_;
417 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
419 TestSharedBitmapManager shared_bitmap_manager_;
420 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
421 TestTaskGraphRunner task_graph_runner_;
422 scoped_ptr<LayerTreeHostImpl> host_impl_;
423 FakeRenderingStatsInstrumentation stats_instrumentation_;
424 bool on_can_draw_state_changed_called_;
425 bool did_notify_ready_to_activate_;
426 bool did_request_commit_;
427 bool did_request_redraw_;
428 bool did_request_animate_;
429 bool did_request_prepare_tiles_;
430 bool did_complete_page_scale_animation_;
431 bool reduce_memory_result_;
432 base::Closure animation_task_;
433 base::TimeDelta requested_animation_delay_;
436 // A test fixture for new animation timelines tests.
437 class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest {
438 public:
439 void SetUp() override {
440 LayerTreeSettings settings = DefaultSettings();
441 settings.use_compositor_animation_timelines = true;
442 CreateHostImpl(settings, CreateOutputSurface());
446 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
447 bool always_draw = false;
448 CheckNotifyCalledIfCanDrawChanged(always_draw);
451 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
452 CreateHostImpl(DefaultSettings(),
453 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
455 bool always_draw = true;
456 CheckNotifyCalledIfCanDrawChanged(always_draw);
459 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
460 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
462 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
463 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
466 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
468 scoped_ptr<LayerImpl> root =
469 LayerImpl::Create(host_impl_->active_tree(), 1);
470 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
471 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
472 root->children()[1]->AddChild(
473 LayerImpl::Create(host_impl_->active_tree(), 4));
474 root->children()[1]->AddChild(
475 LayerImpl::Create(host_impl_->active_tree(), 5));
476 root->children()[1]->children()[0]->AddChild(
477 LayerImpl::Create(host_impl_->active_tree(), 6));
478 host_impl_->active_tree()->SetRootLayer(root.Pass());
480 LayerImpl* root = host_impl_->active_tree()->root_layer();
482 ExpectClearedScrollDeltasRecursive(root);
484 scoped_ptr<ScrollAndScaleSet> scroll_info;
486 scroll_info = host_impl_->ProcessScrollDeltas();
487 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
488 ExpectClearedScrollDeltasRecursive(root);
490 scroll_info = host_impl_->ProcessScrollDeltas();
491 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
492 ExpectClearedScrollDeltasRecursive(root);
495 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
496 gfx::ScrollOffset scroll_offset(20, 30);
497 gfx::Vector2d scroll_delta(11, -15);
499 scoped_ptr<LayerImpl> root_clip =
500 LayerImpl::Create(host_impl_->active_tree(), 2);
501 scoped_ptr<LayerImpl> root =
502 LayerImpl::Create(host_impl_->active_tree(), 1);
503 root_clip->SetBounds(gfx::Size(10, 10));
504 LayerImpl* root_layer = root.get();
505 root_clip->AddChild(root.Pass());
506 root_layer->SetBounds(gfx::Size(110, 110));
507 root_layer->SetScrollClipLayer(root_clip->id());
508 root_layer->PushScrollOffsetFromMainThread(scroll_offset);
509 root_layer->ScrollBy(scroll_delta);
510 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
512 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
514 scoped_ptr<ScrollAndScaleSet> scroll_info;
516 scroll_info = host_impl_->ProcessScrollDeltas();
517 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
518 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(), scroll_delta));
520 gfx::Vector2d scroll_delta2(-5, 27);
521 root->ScrollBy(scroll_delta2);
522 scroll_info = host_impl_->ProcessScrollDeltas();
523 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
524 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(),
525 scroll_delta + scroll_delta2));
527 root->ScrollBy(gfx::Vector2d());
528 scroll_info = host_impl_->ProcessScrollDeltas();
529 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(),
530 scroll_delta + scroll_delta2));
533 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
534 SetupScrollAndContentsLayers(gfx::Size(100, 100));
535 host_impl_->SetViewportSize(gfx::Size(50, 50));
536 DrawFrame();
538 EXPECT_EQ(InputHandler::SCROLL_STARTED,
539 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
540 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
541 InputHandler::WHEEL));
542 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
543 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
544 InputHandler::WHEEL));
545 host_impl_->ScrollEnd();
546 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
547 InputHandler::WHEEL));
548 EXPECT_TRUE(did_request_redraw_);
549 EXPECT_TRUE(did_request_commit_);
552 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
553 SetupScrollAndContentsLayers(gfx::Size(100, 100));
554 host_impl_->SetViewportSize(gfx::Size(50, 50));
555 DrawFrame();
557 EXPECT_EQ(InputHandler::SCROLL_STARTED,
558 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
559 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
560 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
561 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
562 host_impl_->ScrollEnd();
563 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
566 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
567 // We should not crash when trying to scroll an empty layer tree.
568 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
569 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
572 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
573 scoped_ptr<TestWebGraphicsContext3D> context_owned =
574 TestWebGraphicsContext3D::Create();
575 context_owned->set_context_lost(true);
577 // Initialization will fail.
578 EXPECT_FALSE(CreateHostImpl(
579 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
581 SetupScrollAndContentsLayers(gfx::Size(100, 100));
583 // We should not crash when trying to scroll after the renderer initialization
584 // fails.
585 EXPECT_EQ(InputHandler::SCROLL_STARTED,
586 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
589 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
590 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
591 host_impl_->SetViewportSize(gfx::Size(50, 50));
592 DrawFrame();
594 // We should not crash if the tree is replaced while we are scrolling.
595 EXPECT_EQ(InputHandler::SCROLL_STARTED,
596 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
597 host_impl_->active_tree()->DetachLayerTree();
599 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
601 // We should still be scrolling, because the scrolled layer also exists in the
602 // new tree.
603 gfx::Vector2d scroll_delta(0, 10);
604 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
605 host_impl_->ScrollEnd();
606 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
607 EXPECT_TRUE(
608 ScrollInfoContains(*scroll_info, scroll_layer->id(), scroll_delta));
611 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
612 SetupScrollAndContentsLayers(gfx::Size(100, 100));
613 host_impl_->SetViewportSize(gfx::Size(50, 50));
614 DrawFrame();
615 LayerImpl* root = host_impl_->active_tree()->root_layer();
617 // With registered event handlers, wheel scrolls don't necessarily
618 // have to go to the main thread.
619 root->SetHaveWheelEventHandlers(true);
620 EXPECT_EQ(InputHandler::SCROLL_STARTED,
621 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
622 host_impl_->ScrollEnd();
624 // But typically the scroll-blocks-on mode will require them to.
625 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
626 SCROLL_BLOCKS_ON_START_TOUCH);
627 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
628 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
630 // But gesture scrolls can still be handled.
631 EXPECT_EQ(InputHandler::SCROLL_STARTED,
632 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
633 host_impl_->ScrollEnd();
635 // And if the handlers go away, wheel scrolls can again be processed
636 // on impl (despite the scroll-blocks-on mode).
637 root->SetHaveWheelEventHandlers(false);
638 EXPECT_EQ(InputHandler::SCROLL_STARTED,
639 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
640 host_impl_->ScrollEnd();
643 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
644 LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
645 host_impl_->SetViewportSize(gfx::Size(50, 50));
646 DrawFrame();
647 LayerImpl* root = host_impl_->active_tree()->root_layer();
649 LayerImpl* child = 0;
651 scoped_ptr<LayerImpl> child_layer =
652 LayerImpl::Create(host_impl_->active_tree(), 6);
653 child = child_layer.get();
654 child_layer->SetDrawsContent(true);
655 child_layer->SetPosition(gfx::PointF(0, 20));
656 child_layer->SetBounds(gfx::Size(50, 50));
657 scroll->AddChild(child_layer.Pass());
660 // Touch handler regions determine whether touch events block scroll.
661 root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
662 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
663 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH |
664 SCROLL_BLOCKS_ON_WHEEL_EVENT);
665 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
667 // But they don't influence the actual handling of the scroll gestures.
668 EXPECT_EQ(InputHandler::SCROLL_STARTED,
669 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
670 host_impl_->ScrollEnd();
672 // It's the union of scroll-blocks-on mode bits across all layers in the
673 // scroll paret chain that matters.
674 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
675 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE);
676 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
677 child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH);
678 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
681 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
682 SetupScrollAndContentsLayers(gfx::Size(100, 100));
683 host_impl_->SetViewportSize(gfx::Size(50, 50));
684 DrawFrame();
685 LayerImpl* root = host_impl_->active_tree()->root_layer();
687 // With registered scroll handlers, scrolls don't generally have to go
688 // to the main thread.
689 root->SetHaveScrollEventHandlers(true);
690 EXPECT_EQ(InputHandler::SCROLL_STARTED,
691 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
692 host_impl_->ScrollEnd();
694 // Even the default scroll blocks on mode doesn't require this.
695 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
696 SCROLL_BLOCKS_ON_START_TOUCH);
697 EXPECT_EQ(InputHandler::SCROLL_STARTED,
698 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
699 host_impl_->ScrollEnd();
701 // But the page can opt in to blocking on scroll event handlers.
702 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
703 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
704 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
706 // GESTURE and WHEEL scrolls behave identically in this regard.
707 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
708 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
710 // And if the handlers go away, scrolls can again be processed on impl
711 // (despite the scroll-blocks-on mode).
712 root->SetHaveScrollEventHandlers(false);
713 EXPECT_EQ(InputHandler::SCROLL_STARTED,
714 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
715 host_impl_->ScrollEnd();
718 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
719 host_impl_->SetViewportSize(gfx::Size(50, 50));
721 // Create a normal scrollable root layer
722 LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
723 LayerImpl* root_child = root_scroll->children()[0];
724 LayerImpl* root = host_impl_->active_tree()->root_layer();
725 DrawFrame();
727 // Create two child scrollable layers
728 LayerImpl* child1 = 0;
730 scoped_ptr<LayerImpl> scrollable_child_clip_1 =
731 LayerImpl::Create(host_impl_->active_tree(), 6);
732 scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
733 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
734 child1 = scrollable_child_1.get();
735 scrollable_child_1->SetPosition(gfx::Point(5, 5));
736 scrollable_child_1->SetHaveWheelEventHandlers(true);
737 scrollable_child_1->SetHaveScrollEventHandlers(true);
738 scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
739 root_child->AddChild(scrollable_child_clip_1.Pass());
742 LayerImpl* child2 = 0;
744 scoped_ptr<LayerImpl> scrollable_child_clip_2 =
745 LayerImpl::Create(host_impl_->active_tree(), 8);
746 scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
747 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
748 child2 = scrollable_child_2.get();
749 scrollable_child_2->SetPosition(gfx::Point(5, 20));
750 scrollable_child_2->SetHaveWheelEventHandlers(true);
751 scrollable_child_2->SetHaveScrollEventHandlers(true);
752 scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
753 root_child->AddChild(scrollable_child_clip_2.Pass());
756 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
757 EXPECT_EQ(InputHandler::SCROLL_STARTED,
758 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
759 host_impl_->ScrollEnd();
760 child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
761 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
762 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
764 // But not those that hit only other layers.
765 EXPECT_EQ(InputHandler::SCROLL_STARTED,
766 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
767 host_impl_->ScrollEnd();
769 // It's the union of bits set across the scroll ancestor chain that matters.
770 EXPECT_EQ(InputHandler::SCROLL_STARTED,
771 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
772 host_impl_->ScrollEnd();
773 EXPECT_EQ(InputHandler::SCROLL_STARTED,
774 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
775 host_impl_->ScrollEnd();
776 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT);
777 EXPECT_EQ(InputHandler::SCROLL_STARTED,
778 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
779 host_impl_->ScrollEnd();
780 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
781 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
782 child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
783 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
784 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
785 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
786 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
789 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
790 SetupScrollAndContentsLayers(gfx::Size(100, 100));
791 host_impl_->SetViewportSize(gfx::Size(50, 50));
792 DrawFrame();
794 // Ignore the fling since no layer is being scrolled
795 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
797 // Start scrolling a layer
798 EXPECT_EQ(InputHandler::SCROLL_STARTED,
799 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
801 // Now the fling should go ahead since we've started scrolling a layer
802 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
805 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
806 SetupScrollAndContentsLayers(gfx::Size(100, 100));
807 host_impl_->SetViewportSize(gfx::Size(50, 50));
808 DrawFrame();
810 // Ignore the fling since no layer is being scrolled
811 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
813 // Start scrolling a layer
814 EXPECT_EQ(InputHandler::SCROLL_STARTED,
815 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
817 // Now the fling should go ahead since we've started scrolling a layer
818 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
821 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
822 SetupScrollAndContentsLayers(gfx::Size(100, 100));
823 host_impl_->SetViewportSize(gfx::Size(50, 50));
824 DrawFrame();
825 LayerImpl* root = host_impl_->active_tree()->root_layer();
827 root->SetShouldScrollOnMainThread(true);
829 // Start scrolling a layer
830 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
831 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
833 // The fling should be ignored since there's no layer being scrolled impl-side
834 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
837 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
838 SetupScrollAndContentsLayers(gfx::Size(100, 100));
839 host_impl_->SetViewportSize(gfx::Size(50, 50));
840 DrawFrame();
841 LayerImpl* root = host_impl_->active_tree()->root_layer();
843 root->SetShouldScrollOnMainThread(true);
845 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
846 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
847 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
848 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
851 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
852 SetupScrollAndContentsLayers(gfx::Size(200, 200));
853 host_impl_->SetViewportSize(gfx::Size(100, 100));
855 LayerImpl* root = host_impl_->active_tree()->root_layer();
856 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
858 DrawFrame();
860 // All scroll types inside the non-fast scrollable region should fail.
861 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
862 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL));
863 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
864 InputHandler::WHEEL));
865 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
866 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE));
867 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
868 InputHandler::GESTURE));
870 // All scroll types outside this region should succeed.
871 EXPECT_EQ(InputHandler::SCROLL_STARTED,
872 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL));
873 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
874 InputHandler::GESTURE));
875 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
876 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
877 InputHandler::GESTURE));
878 host_impl_->ScrollEnd();
879 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
880 InputHandler::GESTURE));
881 EXPECT_EQ(InputHandler::SCROLL_STARTED,
882 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE));
883 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
884 InputHandler::GESTURE));
885 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
886 host_impl_->ScrollEnd();
887 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
888 InputHandler::GESTURE));
891 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
892 SetupScrollAndContentsLayers(gfx::Size(200, 200));
893 host_impl_->SetViewportSize(gfx::Size(100, 100));
895 LayerImpl* root = host_impl_->active_tree()->root_layer();
896 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
897 root->SetPosition(gfx::PointF(-25.f, 0.f));
899 DrawFrame();
901 // This point would fall into the non-fast scrollable region except that we've
902 // moved the layer down by 25 pixels.
903 EXPECT_EQ(InputHandler::SCROLL_STARTED,
904 host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL));
905 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
906 InputHandler::WHEEL));
907 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
908 host_impl_->ScrollEnd();
910 // This point is still inside the non-fast region.
911 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
912 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL));
915 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
916 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
917 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
918 host_impl_->SetViewportSize(gfx::Size(50, 50));
919 DrawFrame();
921 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
922 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
923 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
924 host_impl_->ScrollEnd();
925 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
928 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
929 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
930 scroll_layer->SetHaveScrollEventHandlers(true);
931 host_impl_->SetViewportSize(gfx::Size(50, 50));
932 DrawFrame();
934 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
935 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
936 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
937 host_impl_->ScrollEnd();
938 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
941 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
942 SetupScrollAndContentsLayers(gfx::Size(200, 200));
943 host_impl_->SetViewportSize(gfx::Size(100, 100));
945 DrawFrame();
947 EXPECT_EQ(InputHandler::SCROLL_STARTED,
948 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
950 // Trying to scroll to the left/top will not succeed.
951 EXPECT_FALSE(
952 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
953 EXPECT_FALSE(
954 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
955 EXPECT_FALSE(
956 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
958 // Scrolling to the right/bottom will succeed.
959 EXPECT_TRUE(
960 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
961 EXPECT_TRUE(
962 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
963 EXPECT_TRUE(
964 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
966 // Scrolling to left/top will now succeed.
967 EXPECT_TRUE(
968 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
969 EXPECT_TRUE(
970 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
971 EXPECT_TRUE(
972 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
974 // Scrolling diagonally against an edge will succeed.
975 EXPECT_TRUE(
976 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
977 EXPECT_TRUE(
978 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
979 EXPECT_TRUE(
980 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
982 // Trying to scroll more than the available space will also succeed.
983 EXPECT_TRUE(
984 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
987 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
988 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
989 host_impl_->SetViewportSize(gfx::Size(100, 1000));
991 DrawFrame();
993 EXPECT_EQ(InputHandler::SCROLL_STARTED,
994 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
996 // Trying to scroll without a vertical scrollbar will fail.
997 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
998 gfx::Point(), SCROLL_FORWARD));
999 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
1000 gfx::Point(), SCROLL_BACKWARD));
1002 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
1003 PaintedScrollbarLayerImpl::Create(
1004 host_impl_->active_tree(),
1006 VERTICAL));
1007 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
1008 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
1009 vertical_scrollbar.get());
1011 // Trying to scroll with a vertical scrollbar will succeed.
1012 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1013 gfx::Point(), SCROLL_FORWARD));
1014 EXPECT_FLOAT_EQ(875.f,
1015 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
1016 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1017 gfx::Point(), SCROLL_BACKWARD));
1020 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
1021 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
1022 host_impl_->SetViewportSize(gfx::Size(100, 100));
1024 gfx::Size overflow_size(400, 400);
1025 ASSERT_EQ(1u, scroll_layer->children().size());
1026 LayerImpl* overflow = scroll_layer->children()[0];
1027 overflow->SetBounds(overflow_size);
1028 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
1029 overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1030 overflow->SetPosition(gfx::PointF());
1032 DrawFrame();
1033 gfx::Point scroll_position(10, 10);
1035 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1036 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1037 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1038 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
1040 gfx::Vector2dF scroll_delta(10, 10);
1041 host_impl_->ScrollBy(scroll_position, scroll_delta);
1042 host_impl_->ScrollEnd();
1043 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1044 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1046 overflow->set_user_scrollable_horizontal(false);
1048 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1049 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1050 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1053 host_impl_->ScrollBy(scroll_position, scroll_delta);
1054 host_impl_->ScrollEnd();
1055 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1056 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1058 overflow->set_user_scrollable_vertical(false);
1060 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1061 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1062 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1063 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1065 host_impl_->ScrollBy(scroll_position, scroll_delta);
1066 host_impl_->ScrollEnd();
1067 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
1068 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1071 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
1072 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
1073 host_impl_->SetViewportSize(gfx::Size(50, 50));
1074 DrawFrame();
1076 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
1077 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
1078 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1080 float min_page_scale = 1.f, max_page_scale = 4.f;
1081 float page_scale_factor = 1.f;
1083 // The impl-based pinch zoom should adjust the max scroll position.
1085 host_impl_->active_tree()->PushPageScaleFromMainThread(
1086 page_scale_factor, min_page_scale, max_page_scale);
1087 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1088 scroll_layer->SetScrollDelta(gfx::Vector2d());
1090 float page_scale_delta = 2.f;
1092 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1093 host_impl_->PinchGestureBegin();
1094 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1095 host_impl_->PinchGestureEnd();
1096 host_impl_->ScrollEnd();
1097 EXPECT_FALSE(did_request_animate_);
1098 EXPECT_TRUE(did_request_redraw_);
1099 EXPECT_TRUE(did_request_commit_);
1100 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1102 scoped_ptr<ScrollAndScaleSet> scroll_info =
1103 host_impl_->ProcessScrollDeltas();
1104 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1106 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1107 scroll_layer->MaxScrollOffset().ToString());
1110 // Scrolling after a pinch gesture should always be in local space. The
1111 // scroll deltas have the page scale factor applied.
1113 host_impl_->active_tree()->PushPageScaleFromMainThread(
1114 page_scale_factor, min_page_scale, max_page_scale);
1115 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1116 scroll_layer->SetScrollDelta(gfx::Vector2d());
1118 float page_scale_delta = 2.f;
1119 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1120 host_impl_->PinchGestureBegin();
1121 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1122 host_impl_->PinchGestureEnd();
1123 host_impl_->ScrollEnd();
1125 gfx::Vector2d scroll_delta(0, 10);
1126 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1127 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
1128 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1129 host_impl_->ScrollEnd();
1131 scoped_ptr<ScrollAndScaleSet> scroll_info =
1132 host_impl_->ProcessScrollDeltas();
1133 EXPECT_TRUE(ScrollInfoContains(
1134 *scroll_info.get(), scroll_layer->id(),
1135 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta)));
1139 TEST_F(LayerTreeHostImplTest, ScrollDuringPinchScrollsInnerViewport) {
1140 LayerTreeSettings settings = DefaultSettings();
1141 settings.invert_viewport_scroll_order = true;
1142 CreateHostImpl(settings,
1143 CreateOutputSurface());
1145 const gfx::Size content_size(1000, 1000);
1146 const gfx::Size viewport_size(500, 500);
1147 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1149 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1150 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1152 EXPECT_VECTOR_EQ(
1153 gfx::Vector2dF(500, 500),
1154 outer_scroll_layer->MaxScrollOffset());
1156 host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
1157 host_impl_->PinchGestureBegin();
1158 host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
1159 host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f));
1160 host_impl_->PinchGestureEnd();
1161 host_impl_->ScrollEnd();
1163 EXPECT_VECTOR_EQ(
1164 gfx::Vector2dF(0, 0),
1165 outer_scroll_layer->CurrentScrollOffset());
1166 EXPECT_VECTOR_EQ(
1167 gfx::Vector2dF(130, 130),
1168 inner_scroll_layer->CurrentScrollOffset());
1171 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1172 // a pinch zoom is anchored within a certain margin of the screen edge, we
1173 // should assume the user means to scroll into the edge of the screen.
1174 TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
1175 LayerTreeSettings settings = DefaultSettings();
1176 settings.invert_viewport_scroll_order = true;
1177 CreateHostImpl(settings,
1178 CreateOutputSurface());
1180 const gfx::Size content_size(1000, 1000);
1181 const gfx::Size viewport_size(500, 500);
1182 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1184 int offsetFromEdge = Viewport::kPinchZoomSnapMarginDips - 5;
1185 gfx::Point anchor(viewport_size.width() - offsetFromEdge,
1186 viewport_size.height() - offsetFromEdge);
1188 // Pinch in within the margins. The scroll should stay exactly locked to the
1189 // bottom and right.
1190 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1191 host_impl_->PinchGestureBegin();
1192 host_impl_->PinchGestureUpdate(2, anchor);
1193 host_impl_->PinchGestureEnd();
1194 host_impl_->ScrollEnd();
1196 EXPECT_VECTOR_EQ(
1197 gfx::Vector2dF(250, 250),
1198 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1200 // Reset.
1201 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1202 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1203 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1205 // Pinch in within the margins. The scroll should stay exactly locked to the
1206 // top and left.
1207 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1208 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1209 host_impl_->PinchGestureBegin();
1210 host_impl_->PinchGestureUpdate(2, anchor);
1211 host_impl_->PinchGestureEnd();
1212 host_impl_->ScrollEnd();
1214 EXPECT_VECTOR_EQ(
1215 gfx::Vector2dF(0, 0),
1216 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1218 // Reset.
1219 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1220 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1221 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1223 // Pinch in just outside the margin. There should be no snapping.
1224 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1225 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1226 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1227 host_impl_->PinchGestureBegin();
1228 host_impl_->PinchGestureUpdate(2, anchor);
1229 host_impl_->PinchGestureEnd();
1230 host_impl_->ScrollEnd();
1232 EXPECT_VECTOR_EQ(
1233 gfx::Vector2dF(50, 50),
1234 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1236 // Reset.
1237 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1238 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1239 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1241 // Pinch in just outside the margin. There should be no snapping.
1242 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1243 anchor = gfx::Point(viewport_size.width() - offsetFromEdge,
1244 viewport_size.height() - offsetFromEdge);
1245 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1246 host_impl_->PinchGestureBegin();
1247 host_impl_->PinchGestureUpdate(2, anchor);
1248 host_impl_->PinchGestureEnd();
1249 host_impl_->ScrollEnd();
1251 EXPECT_VECTOR_EQ(
1252 gfx::Vector2dF(200, 200),
1253 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1256 TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
1257 const gfx::Size content_size(200, 200);
1258 const gfx::Size viewport_size(100, 100);
1259 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1261 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1262 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1264 // Zoom into the page by a 2X factor
1265 float min_page_scale = 1.f, max_page_scale = 4.f;
1266 float page_scale_factor = 2.f;
1267 host_impl_->active_tree()->PushPageScaleFromMainThread(
1268 page_scale_factor, min_page_scale, max_page_scale);
1269 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1271 // Scroll by a small amount, there should be no bubbling up to the inner
1272 // viewport.
1273 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1274 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f));
1275 host_impl_->ScrollEnd();
1277 EXPECT_VECTOR_EQ(
1278 gfx::Vector2dF(5, 10),
1279 outer_scroll_layer->CurrentScrollOffset());
1280 EXPECT_VECTOR_EQ(
1281 gfx::Vector2dF(),
1282 inner_scroll_layer->CurrentScrollOffset());
1284 // Scroll by the outer viewport's max scroll extent, there the remainder
1285 // should bubble up to the inner viewport.
1286 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1287 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f));
1288 host_impl_->ScrollEnd();
1290 EXPECT_VECTOR_EQ(
1291 gfx::Vector2dF(100, 100),
1292 outer_scroll_layer->CurrentScrollOffset());
1293 EXPECT_VECTOR_EQ(
1294 gfx::Vector2dF(5, 10),
1295 inner_scroll_layer->CurrentScrollOffset());
1297 // Scroll by the inner viewport's max scroll extent, it should all go to the
1298 // inner viewport.
1299 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1300 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f, 80.f));
1301 host_impl_->ScrollEnd();
1303 EXPECT_VECTOR_EQ(
1304 gfx::Vector2dF(100, 100),
1305 outer_scroll_layer->CurrentScrollOffset());
1306 EXPECT_VECTOR_EQ(
1307 gfx::Vector2dF(50, 50),
1308 inner_scroll_layer->CurrentScrollOffset());
1311 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
1312 ui::LatencyInfo latency_info;
1313 latency_info.trace_id = 1234;
1314 scoped_ptr<SwapPromise> swap_promise(
1315 new LatencyInfoSwapPromise(latency_info));
1317 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1318 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1319 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
1320 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1321 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
1322 host_impl_->ScrollEnd();
1324 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1325 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1326 EXPECT_EQ(latency_info.trace_id, scroll_info->swap_promises[0]->TraceId());
1329 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1330 // up to the scroll_parent, rather than the stacking parent.
1331 TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
1332 LayerImpl* viewport_scroll =
1333 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1334 host_impl_->SetViewportSize(gfx::Size(50, 50));
1336 // Set up two scrolling children of the root, one of which is a scroll parent
1337 // to the other. Scrolls bubbling from the child should bubble to the parent,
1338 // not the viewport.
1339 LayerImpl *parent;
1340 LayerImpl *child;
1341 LayerImpl *child_clip;
1343 scoped_ptr<LayerImpl> scroll_parent_clip =
1344 LayerImpl::Create(host_impl_->active_tree(), 6);
1345 scoped_ptr<LayerImpl> scroll_parent = CreateScrollableLayer(
1346 7, gfx::Size(10, 10), scroll_parent_clip.get());
1347 parent = scroll_parent.get();
1348 scroll_parent_clip->AddChild(scroll_parent.Pass());
1350 viewport_scroll->AddChild(scroll_parent_clip.Pass());
1352 scoped_ptr<LayerImpl> scroll_child_clip =
1353 LayerImpl::Create(host_impl_->active_tree(), 8);
1354 scoped_ptr<LayerImpl> scroll_child = CreateScrollableLayer(
1355 9, gfx::Size(10, 10), scroll_child_clip.get());
1356 child = scroll_child.get();
1357 scroll_child->SetPosition(gfx::Point(20, 20));
1358 scroll_child_clip->AddChild(scroll_child.Pass());
1360 child_clip = scroll_child_clip.get();
1361 viewport_scroll->AddChild(scroll_child_clip.Pass());
1363 child_clip->SetScrollParent(parent);
1365 DrawFrame();
1368 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1369 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1370 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1371 host_impl_->ScrollEnd();
1373 // The child should be fully scrolled by the first ScrollBy.
1374 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child->CurrentScrollOffset());
1376 // The scroll_parent should receive the bubbled up second ScrollBy.
1377 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent->CurrentScrollOffset());
1379 // The viewport shouldn't have been scrolled at all.
1380 EXPECT_VECTOR_EQ(
1381 gfx::Vector2dF(0, 0),
1382 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1383 EXPECT_VECTOR_EQ(
1384 gfx::Vector2dF(0, 0),
1385 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1389 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1390 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1391 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1392 host_impl_->ScrollEnd();
1394 // The first ScrollBy should scroll the parent to its extent.
1395 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent->CurrentScrollOffset());
1397 // The viewport should now be next in bubbling order.
1398 EXPECT_VECTOR_EQ(
1399 gfx::Vector2dF(2, 1),
1400 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1401 EXPECT_VECTOR_EQ(
1402 gfx::Vector2dF(0, 0),
1403 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1408 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1409 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1410 host_impl_->SetViewportSize(gfx::Size(50, 50));
1411 DrawFrame();
1413 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1414 DCHECK(scroll_layer);
1416 float min_page_scale = 1.f;
1417 float max_page_scale = 4.f;
1419 // Basic pinch zoom in gesture
1421 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1422 max_page_scale);
1423 scroll_layer->SetScrollDelta(gfx::Vector2d());
1425 float page_scale_delta = 2.f;
1426 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1427 host_impl_->PinchGestureBegin();
1428 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1429 host_impl_->PinchGestureEnd();
1430 host_impl_->ScrollEnd();
1431 EXPECT_FALSE(did_request_animate_);
1432 EXPECT_TRUE(did_request_redraw_);
1433 EXPECT_TRUE(did_request_commit_);
1435 scoped_ptr<ScrollAndScaleSet> scroll_info =
1436 host_impl_->ProcessScrollDeltas();
1437 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1440 // Zoom-in clamping
1442 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1443 max_page_scale);
1444 scroll_layer->SetScrollDelta(gfx::Vector2d());
1445 float page_scale_delta = 10.f;
1447 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1448 host_impl_->PinchGestureBegin();
1449 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1450 host_impl_->PinchGestureEnd();
1451 host_impl_->ScrollEnd();
1453 scoped_ptr<ScrollAndScaleSet> scroll_info =
1454 host_impl_->ProcessScrollDeltas();
1455 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1458 // Zoom-out clamping
1460 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1461 max_page_scale);
1462 scroll_layer->SetScrollDelta(gfx::Vector2d());
1463 scroll_layer->PullDeltaForMainThread();
1464 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1466 float page_scale_delta = 0.1f;
1467 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1468 host_impl_->PinchGestureBegin();
1469 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1470 host_impl_->PinchGestureEnd();
1471 host_impl_->ScrollEnd();
1473 scoped_ptr<ScrollAndScaleSet> scroll_info =
1474 host_impl_->ProcessScrollDeltas();
1475 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1477 EXPECT_TRUE(scroll_info->scrolls.empty());
1480 // Two-finger panning should not happen based on pinch events only
1482 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1483 max_page_scale);
1484 scroll_layer->SetScrollDelta(gfx::Vector2d());
1485 scroll_layer->PullDeltaForMainThread();
1486 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1488 float page_scale_delta = 1.f;
1489 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1490 host_impl_->PinchGestureBegin();
1491 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1492 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1493 host_impl_->PinchGestureEnd();
1494 host_impl_->ScrollEnd();
1496 scoped_ptr<ScrollAndScaleSet> scroll_info =
1497 host_impl_->ProcessScrollDeltas();
1498 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1499 EXPECT_TRUE(scroll_info->scrolls.empty());
1502 // Two-finger panning should work with interleaved scroll events
1504 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1505 max_page_scale);
1506 scroll_layer->SetScrollDelta(gfx::Vector2d());
1507 scroll_layer->PullDeltaForMainThread();
1508 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1510 float page_scale_delta = 1.f;
1511 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1512 host_impl_->PinchGestureBegin();
1513 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1514 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1515 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1516 host_impl_->PinchGestureEnd();
1517 host_impl_->ScrollEnd();
1519 scoped_ptr<ScrollAndScaleSet> scroll_info =
1520 host_impl_->ProcessScrollDeltas();
1521 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1522 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1523 gfx::Vector2d(-10, -10)));
1526 // Two-finger panning should work when starting fully zoomed out.
1528 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1529 scroll_layer->SetScrollDelta(gfx::Vector2d());
1530 scroll_layer->PullDeltaForMainThread();
1531 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1533 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1534 host_impl_->PinchGestureBegin();
1535 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1536 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1537 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1538 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1539 host_impl_->PinchGestureEnd();
1540 host_impl_->ScrollEnd();
1542 scoped_ptr<ScrollAndScaleSet> scroll_info =
1543 host_impl_->ProcessScrollDeltas();
1544 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1545 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1546 gfx::Vector2d(20, 20)));
1550 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1551 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1552 host_impl_->SetViewportSize(gfx::Size(50, 50));
1553 DrawFrame();
1555 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1556 DCHECK(scroll_layer);
1558 float min_page_scale = 0.5f;
1559 float max_page_scale = 4.f;
1560 base::TimeTicks start_time = base::TimeTicks() +
1561 base::TimeDelta::FromSeconds(1);
1562 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1563 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1564 base::TimeTicks end_time = start_time + duration;
1566 // Non-anchor zoom-in
1568 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1569 max_page_scale);
1570 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1572 did_request_redraw_ = false;
1573 did_request_animate_ = false;
1574 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1575 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1576 gfx::Vector2d(),
1577 false,
1578 2.f,
1579 duration)));
1580 host_impl_->ActivateSyncTree();
1581 EXPECT_FALSE(did_request_redraw_);
1582 EXPECT_TRUE(did_request_animate_);
1584 did_request_redraw_ = false;
1585 did_request_animate_ = false;
1586 host_impl_->Animate(start_time);
1587 EXPECT_TRUE(did_request_redraw_);
1588 EXPECT_TRUE(did_request_animate_);
1590 did_request_redraw_ = false;
1591 did_request_animate_ = false;
1592 host_impl_->Animate(halfway_through_animation);
1593 EXPECT_TRUE(did_request_redraw_);
1594 EXPECT_TRUE(did_request_animate_);
1596 did_request_redraw_ = false;
1597 did_request_animate_ = false;
1598 did_request_commit_ = false;
1599 host_impl_->Animate(end_time);
1600 EXPECT_TRUE(did_request_commit_);
1601 EXPECT_FALSE(did_request_animate_);
1603 scoped_ptr<ScrollAndScaleSet> scroll_info =
1604 host_impl_->ProcessScrollDeltas();
1605 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1606 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1607 gfx::Vector2d(-50, -50)));
1610 // Anchor zoom-out
1612 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1613 max_page_scale);
1614 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1616 did_request_redraw_ = false;
1617 did_request_animate_ = false;
1618 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1619 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1620 gfx::Vector2d(25, 25),
1621 true,
1622 min_page_scale,
1623 duration)));
1624 host_impl_->ActivateSyncTree();
1625 EXPECT_FALSE(did_request_redraw_);
1626 EXPECT_TRUE(did_request_animate_);
1628 did_request_redraw_ = false;
1629 did_request_animate_ = false;
1630 host_impl_->Animate(start_time);
1631 EXPECT_TRUE(did_request_redraw_);
1632 EXPECT_TRUE(did_request_animate_);
1634 did_request_redraw_ = false;
1635 did_request_commit_ = false;
1636 did_request_animate_ = false;
1637 host_impl_->Animate(end_time);
1638 EXPECT_TRUE(did_request_redraw_);
1639 EXPECT_FALSE(did_request_animate_);
1640 EXPECT_TRUE(did_request_commit_);
1642 scoped_ptr<ScrollAndScaleSet> scroll_info =
1643 host_impl_->ProcessScrollDeltas();
1644 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1645 // Pushed to (0,0) via clamping against contents layer size.
1646 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1647 gfx::Vector2d(-50, -50)));
1651 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1652 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1653 host_impl_->SetViewportSize(gfx::Size(50, 50));
1654 DrawFrame();
1656 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1657 DCHECK(scroll_layer);
1659 float min_page_scale = 0.5f;
1660 float max_page_scale = 4.f;
1661 base::TimeTicks start_time = base::TimeTicks() +
1662 base::TimeDelta::FromSeconds(1);
1663 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1664 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1665 base::TimeTicks end_time = start_time + duration;
1667 // Anchor zoom with unchanged page scale should not change scroll or scale.
1669 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1670 max_page_scale);
1671 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1673 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1674 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1675 gfx::Vector2d(),
1676 true,
1677 1.f,
1678 duration)));
1679 host_impl_->ActivateSyncTree();
1680 host_impl_->Animate(start_time);
1681 host_impl_->Animate(halfway_through_animation);
1682 EXPECT_TRUE(did_request_redraw_);
1683 host_impl_->Animate(end_time);
1684 EXPECT_TRUE(did_request_commit_);
1686 scoped_ptr<ScrollAndScaleSet> scroll_info =
1687 host_impl_->ProcessScrollDeltas();
1688 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1689 ExpectNone(*scroll_info, scroll_layer->id());
1693 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1694 host_impl_->CreatePendingTree();
1695 CreateScrollAndContentsLayers(
1696 host_impl_->pending_tree(),
1697 gfx::Size(100, 100));
1698 host_impl_->ActivateSyncTree();
1699 DrawFrame();
1701 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1702 DCHECK(scroll_layer);
1704 float min_page_scale = 0.5f;
1705 float max_page_scale = 4.f;
1706 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1707 max_page_scale);
1708 host_impl_->ActivateSyncTree();
1710 base::TimeTicks start_time = base::TimeTicks() +
1711 base::TimeDelta::FromSeconds(1);
1712 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1713 base::TimeTicks third_through_animation = start_time + duration / 3;
1714 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1715 base::TimeTicks end_time = start_time + duration;
1716 float target_scale = 2.f;
1718 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1720 // Make sure TakePageScaleAnimation works properly.
1722 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1723 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1724 gfx::Vector2d(),
1725 false,
1726 target_scale,
1727 duration)));
1728 scoped_ptr<PendingPageScaleAnimation> psa =
1729 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1730 EXPECT_EQ(target_scale, psa->scale);
1731 EXPECT_EQ(duration, psa->duration);
1732 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1734 // Recreate the PSA. Nothing should happen here since the tree containing the
1735 // PSA hasn't been activated yet.
1736 did_request_redraw_ = false;
1737 did_request_animate_ = false;
1738 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1739 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1740 gfx::Vector2d(),
1741 false,
1742 target_scale,
1743 duration)));
1744 host_impl_->Animate(halfway_through_animation);
1745 EXPECT_FALSE(did_request_animate_);
1746 EXPECT_FALSE(did_request_redraw_);
1748 // Activate the sync tree. This should cause the animation to become enabled.
1749 // It should also clear the pointer on the sync tree.
1750 host_impl_->ActivateSyncTree();
1751 EXPECT_EQ(nullptr,
1752 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1753 EXPECT_FALSE(did_request_redraw_);
1754 EXPECT_TRUE(did_request_animate_);
1756 // From here on, make sure the animation runs as normal.
1757 did_request_redraw_ = false;
1758 did_request_animate_ = false;
1759 host_impl_->Animate(start_time);
1760 EXPECT_TRUE(did_request_redraw_);
1761 EXPECT_TRUE(did_request_animate_);
1763 did_request_redraw_ = false;
1764 did_request_animate_ = false;
1765 host_impl_->Animate(third_through_animation);
1766 EXPECT_TRUE(did_request_redraw_);
1767 EXPECT_TRUE(did_request_animate_);
1769 // Another activation shouldn't have any effect on the animation.
1770 host_impl_->ActivateSyncTree();
1772 did_request_redraw_ = false;
1773 did_request_animate_ = false;
1774 host_impl_->Animate(halfway_through_animation);
1775 EXPECT_TRUE(did_request_redraw_);
1776 EXPECT_TRUE(did_request_animate_);
1778 did_request_redraw_ = false;
1779 did_request_animate_ = false;
1780 did_request_commit_ = false;
1781 host_impl_->Animate(end_time);
1782 EXPECT_TRUE(did_request_commit_);
1783 EXPECT_FALSE(did_request_animate_);
1785 scoped_ptr<ScrollAndScaleSet> scroll_info =
1786 host_impl_->ProcessScrollDeltas();
1787 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
1788 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1789 gfx::Vector2d(-50, -50)));
1792 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
1793 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1794 host_impl_->SetViewportSize(gfx::Size(50, 50));
1795 DrawFrame();
1797 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1798 DCHECK(scroll_layer);
1800 base::TimeTicks start_time =
1801 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1802 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1803 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1804 base::TimeTicks end_time = start_time + duration;
1806 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1807 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1809 did_complete_page_scale_animation_ = false;
1810 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1811 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1812 gfx::Vector2d(), false, 2.f, duration)));
1813 host_impl_->ActivateSyncTree();
1814 host_impl_->Animate(start_time);
1815 EXPECT_FALSE(did_complete_page_scale_animation_);
1817 host_impl_->Animate(halfway_through_animation);
1818 EXPECT_FALSE(did_complete_page_scale_animation_);
1820 host_impl_->Animate(end_time);
1821 EXPECT_TRUE(did_complete_page_scale_animation_);
1824 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1825 public:
1826 LayerTreeHostImplOverridePhysicalTime(
1827 const LayerTreeSettings& settings,
1828 LayerTreeHostImplClient* client,
1829 Proxy* proxy,
1830 SharedBitmapManager* manager,
1831 TaskGraphRunner* task_graph_runner,
1832 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1833 : LayerTreeHostImpl(settings,
1834 client,
1835 proxy,
1836 rendering_stats_instrumentation,
1837 manager,
1838 nullptr,
1839 task_graph_runner,
1840 0) {}
1842 BeginFrameArgs CurrentBeginFrameArgs() const override {
1843 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
1844 fake_current_physical_time_);
1847 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1848 fake_current_physical_time_ = fake_now;
1851 private:
1852 base::TimeTicks fake_current_physical_time_;
1855 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
1856 protected:
1857 void SetupLayers(LayerTreeSettings settings) {
1858 gfx::Size viewport_size(10, 10);
1859 gfx::Size content_size(100, 100);
1861 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1862 new LayerTreeHostImplOverridePhysicalTime(
1863 settings, this, &proxy_, &shared_bitmap_manager_,
1864 &task_graph_runner_, &stats_instrumentation_);
1865 host_impl_ = make_scoped_ptr(host_impl_override_time);
1866 host_impl_->InitializeRenderer(CreateOutputSurface());
1867 host_impl_->SetViewportSize(viewport_size);
1869 scoped_ptr<LayerImpl> root =
1870 LayerImpl::Create(host_impl_->active_tree(), 1);
1871 root->SetBounds(viewport_size);
1873 scoped_ptr<LayerImpl> scroll =
1874 LayerImpl::Create(host_impl_->active_tree(), 2);
1875 scroll->SetScrollClipLayer(root->id());
1876 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1877 root->SetBounds(viewport_size);
1878 scroll->SetBounds(content_size);
1879 scroll->SetIsContainerForFixedPositionLayers(true);
1881 scoped_ptr<LayerImpl> contents =
1882 LayerImpl::Create(host_impl_->active_tree(), 3);
1883 contents->SetDrawsContent(true);
1884 contents->SetBounds(content_size);
1886 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
1887 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 4,
1888 VERTICAL, 10, 0, false, true);
1889 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
1891 scroll->AddChild(contents.Pass());
1892 root->AddChild(scroll.Pass());
1893 root->SetHasRenderSurface(true);
1894 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
1895 root->AddChild(scrollbar.Pass());
1897 host_impl_->active_tree()->SetRootLayer(root.Pass());
1898 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
1899 Layer::INVALID_ID);
1900 host_impl_->active_tree()->DidBecomeActive();
1901 DrawFrame();
1904 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
1905 LayerTreeSettings settings;
1906 settings.scrollbar_animator = animator;
1907 settings.scrollbar_fade_delay_ms = 20;
1908 settings.scrollbar_fade_duration_ms = 20;
1910 SetupLayers(settings);
1912 base::TimeTicks fake_now = base::TimeTicks::Now();
1914 EXPECT_FALSE(did_request_animate_);
1915 EXPECT_FALSE(did_request_redraw_);
1916 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1917 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1919 // If no scroll happened during a scroll gesture, it should have no effect.
1920 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1921 host_impl_->ScrollEnd();
1922 EXPECT_FALSE(did_request_animate_);
1923 EXPECT_FALSE(did_request_redraw_);
1924 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1925 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1927 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1928 // now.
1929 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1930 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1931 EXPECT_FALSE(did_request_animate_);
1932 EXPECT_TRUE(did_request_redraw_);
1933 did_request_redraw_ = false;
1934 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1935 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1937 host_impl_->ScrollEnd();
1938 EXPECT_FALSE(did_request_animate_);
1939 EXPECT_FALSE(did_request_redraw_);
1940 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1941 requested_animation_delay_);
1942 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1944 fake_now += requested_animation_delay_;
1945 requested_animation_delay_ = base::TimeDelta();
1946 animation_task_.Run();
1947 animation_task_ = base::Closure();
1948 EXPECT_TRUE(did_request_animate_);
1949 did_request_animate_ = false;
1950 EXPECT_FALSE(did_request_redraw_);
1952 // After the scrollbar animation begins, we should start getting redraws.
1953 host_impl_->Animate(fake_now);
1954 EXPECT_TRUE(did_request_animate_);
1955 did_request_animate_ = false;
1956 EXPECT_TRUE(did_request_redraw_);
1957 did_request_redraw_ = false;
1958 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1959 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1961 // Setting the scroll offset outside a scroll should also cause the
1962 // scrollbar to appear and to schedule a scrollbar animation.
1963 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1964 gfx::ScrollOffset(5, 5));
1965 EXPECT_FALSE(did_request_animate_);
1966 EXPECT_FALSE(did_request_redraw_);
1967 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1968 requested_animation_delay_);
1969 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1970 requested_animation_delay_ = base::TimeDelta();
1971 animation_task_ = base::Closure();
1973 // Scrollbar animation is not triggered unnecessarily.
1974 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1975 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1976 EXPECT_FALSE(did_request_animate_);
1977 EXPECT_TRUE(did_request_redraw_);
1978 did_request_redraw_ = false;
1979 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1980 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1982 host_impl_->ScrollEnd();
1983 EXPECT_FALSE(did_request_animate_);
1984 EXPECT_FALSE(did_request_redraw_);
1985 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1986 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1988 // Changing page scale triggers scrollbar animation.
1989 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
1990 host_impl_->SetPageScaleOnActiveTree(1.1f);
1991 EXPECT_FALSE(did_request_animate_);
1992 EXPECT_FALSE(did_request_redraw_);
1993 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1994 requested_animation_delay_);
1995 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1996 requested_animation_delay_ = base::TimeDelta();
1997 animation_task_ = base::Closure();
2001 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
2002 RunTest(LayerTreeSettings::LINEAR_FADE);
2005 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
2006 RunTest(LayerTreeSettings::THINNING);
2009 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2010 float device_scale_factor) {
2011 LayerTreeSettings settings;
2012 settings.scrollbar_fade_delay_ms = 500;
2013 settings.scrollbar_fade_duration_ms = 300;
2014 settings.scrollbar_animator = LayerTreeSettings::THINNING;
2016 gfx::Size viewport_size(300, 200);
2017 gfx::Size device_viewport_size = gfx::ToFlooredSize(
2018 gfx::ScaleSize(viewport_size, device_scale_factor));
2019 gfx::Size content_size(1000, 1000);
2021 CreateHostImpl(settings, CreateOutputSurface());
2022 host_impl_->SetDeviceScaleFactor(device_scale_factor);
2023 host_impl_->SetViewportSize(device_viewport_size);
2025 scoped_ptr<LayerImpl> root =
2026 LayerImpl::Create(host_impl_->active_tree(), 1);
2027 root->SetBounds(viewport_size);
2028 root->SetHasRenderSurface(true);
2030 scoped_ptr<LayerImpl> scroll =
2031 LayerImpl::Create(host_impl_->active_tree(), 2);
2032 scroll->SetScrollClipLayer(root->id());
2033 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2034 scroll->SetBounds(content_size);
2035 scroll->SetIsContainerForFixedPositionLayers(true);
2037 scoped_ptr<LayerImpl> contents =
2038 LayerImpl::Create(host_impl_->active_tree(), 3);
2039 contents->SetDrawsContent(true);
2040 contents->SetBounds(content_size);
2042 // The scrollbar is on the right side.
2043 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
2044 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
2045 scrollbar->SetDrawsContent(true);
2046 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
2047 scrollbar->SetPosition(gfx::Point(285, 0));
2049 scroll->AddChild(contents.Pass());
2050 root->AddChild(scroll.Pass());
2051 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
2052 root->AddChild(scrollbar.Pass());
2054 host_impl_->active_tree()->SetRootLayer(root.Pass());
2055 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
2056 Layer::INVALID_ID);
2057 host_impl_->active_tree()->DidBecomeActive();
2058 DrawFrame();
2060 LayerImpl* root_scroll =
2061 host_impl_->active_tree()->InnerViewportScrollLayer();
2062 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
2063 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
2064 static_cast<ScrollbarAnimationControllerThinning*>(
2065 root_scroll->scrollbar_animation_controller());
2066 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
2068 host_impl_->MouseMoveAt(gfx::Point(1, 1));
2069 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2071 host_impl_->MouseMoveAt(gfx::Point(200, 50));
2072 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2074 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2075 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2077 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
2078 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2079 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2081 did_request_redraw_ = false;
2082 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2083 host_impl_->MouseMoveAt(gfx::Point(290, 100));
2084 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2085 host_impl_->MouseMoveAt(gfx::Point(290, 120));
2086 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2087 host_impl_->MouseMoveAt(gfx::Point(150, 120));
2088 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2091 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
2092 SetupMouseMoveAtWithDeviceScale(1.f);
2095 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
2096 SetupMouseMoveAtWithDeviceScale(2.f);
2099 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
2100 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2101 host_impl_->SetViewportSize(gfx::Size(50, 50));
2102 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
2103 DrawFrame();
2105 CompositorFrameMetadata metadata =
2106 host_impl_->MakeCompositorFrameMetadata();
2107 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
2108 EXPECT_EQ(1.f, metadata.page_scale_factor);
2109 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
2110 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2111 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2112 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2113 EXPECT_FALSE(metadata.root_overflow_x_hidden);
2114 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2117 // Scrolling should update metadata immediately.
2118 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2119 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2120 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2122 CompositorFrameMetadata metadata =
2123 host_impl_->MakeCompositorFrameMetadata();
2124 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2126 host_impl_->ScrollEnd();
2128 CompositorFrameMetadata metadata =
2129 host_impl_->MakeCompositorFrameMetadata();
2130 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2133 // Root "overflow: hidden" properties should be reflected on the outer
2134 // viewport scroll layer.
2136 host_impl_->active_tree()
2137 ->OuterViewportScrollLayer()
2138 ->set_user_scrollable_horizontal(false);
2139 CompositorFrameMetadata metadata =
2140 host_impl_->MakeCompositorFrameMetadata();
2141 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2142 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2144 host_impl_->active_tree()
2145 ->OuterViewportScrollLayer()
2146 ->set_user_scrollable_vertical(false);
2147 metadata = host_impl_->MakeCompositorFrameMetadata();
2148 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2149 EXPECT_TRUE(metadata.root_overflow_y_hidden);
2152 // Page scale should update metadata correctly (shrinking only the viewport).
2153 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
2154 host_impl_->PinchGestureBegin();
2155 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
2156 host_impl_->PinchGestureEnd();
2157 host_impl_->ScrollEnd();
2159 CompositorFrameMetadata metadata =
2160 host_impl_->MakeCompositorFrameMetadata();
2161 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2162 EXPECT_EQ(2.f, metadata.page_scale_factor);
2163 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
2164 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2165 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2166 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2169 // Likewise if set from the main thread.
2170 host_impl_->ProcessScrollDeltas();
2171 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
2172 host_impl_->SetPageScaleOnActiveTree(4.f);
2174 CompositorFrameMetadata metadata =
2175 host_impl_->MakeCompositorFrameMetadata();
2176 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2177 EXPECT_EQ(4.f, metadata.page_scale_factor);
2178 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
2179 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2180 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2181 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2185 class DidDrawCheckLayer : public LayerImpl {
2186 public:
2187 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
2188 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
2191 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
2192 will_draw_called_ = true;
2193 if (will_draw_returns_false_)
2194 return false;
2195 return LayerImpl::WillDraw(draw_mode, provider);
2198 void AppendQuads(RenderPass* render_pass,
2199 AppendQuadsData* append_quads_data) override {
2200 append_quads_called_ = true;
2201 LayerImpl::AppendQuads(render_pass, append_quads_data);
2204 void DidDraw(ResourceProvider* provider) override {
2205 did_draw_called_ = true;
2206 LayerImpl::DidDraw(provider);
2209 bool will_draw_called() const { return will_draw_called_; }
2210 bool append_quads_called() const { return append_quads_called_; }
2211 bool did_draw_called() const { return did_draw_called_; }
2213 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
2215 void ClearDidDrawCheck() {
2216 will_draw_called_ = false;
2217 append_quads_called_ = false;
2218 did_draw_called_ = false;
2221 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
2223 void AddCopyRequest() {
2224 ScopedPtrVector<CopyOutputRequest> requests;
2225 requests.push_back(
2226 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
2227 SetHasRenderSurface(true);
2228 PassCopyRequests(&requests);
2231 protected:
2232 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
2233 : LayerImpl(tree_impl, id),
2234 will_draw_returns_false_(false),
2235 will_draw_called_(false),
2236 append_quads_called_(false),
2237 did_draw_called_(false) {
2238 SetBounds(gfx::Size(10, 10));
2239 SetDrawsContent(true);
2240 draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10);
2243 private:
2244 bool will_draw_returns_false_;
2245 bool will_draw_called_;
2246 bool append_quads_called_;
2247 bool did_draw_called_;
2250 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
2251 // The root layer is always drawn, so run this test on a child layer that
2252 // will be masked out by the root layer's bounds.
2253 host_impl_->active_tree()->SetRootLayer(
2254 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2255 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2256 host_impl_->active_tree()->root_layer());
2258 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2259 root->SetHasRenderSurface(true);
2260 DidDrawCheckLayer* layer =
2261 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2264 LayerTreeHostImpl::FrameData frame;
2265 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2266 host_impl_->DrawLayers(&frame);
2267 host_impl_->DidDrawAllLayers(frame);
2269 EXPECT_TRUE(layer->will_draw_called());
2270 EXPECT_TRUE(layer->append_quads_called());
2271 EXPECT_TRUE(layer->did_draw_called());
2274 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
2277 LayerTreeHostImpl::FrameData frame;
2279 layer->set_will_draw_returns_false();
2280 layer->ClearDidDrawCheck();
2282 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2283 host_impl_->DrawLayers(&frame);
2284 host_impl_->DidDrawAllLayers(frame);
2286 EXPECT_TRUE(layer->will_draw_called());
2287 EXPECT_FALSE(layer->append_quads_called());
2288 EXPECT_FALSE(layer->did_draw_called());
2292 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
2293 // The root layer is always drawn, so run this test on a child layer that
2294 // will be masked out by the root layer's bounds.
2295 host_impl_->active_tree()->SetRootLayer(
2296 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2297 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2298 host_impl_->active_tree()->root_layer());
2299 root->SetMasksToBounds(true);
2300 root->SetHasRenderSurface(true);
2301 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2302 DidDrawCheckLayer* layer =
2303 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2304 // Ensure visible_layer_rect for layer is empty.
2305 layer->SetPosition(gfx::PointF(100.f, 100.f));
2306 layer->SetBounds(gfx::Size(10, 10));
2308 LayerTreeHostImpl::FrameData frame;
2310 EXPECT_FALSE(layer->will_draw_called());
2311 EXPECT_FALSE(layer->did_draw_called());
2313 host_impl_->active_tree()->BuildPropertyTreesForTesting();
2314 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2315 host_impl_->DrawLayers(&frame);
2316 host_impl_->DidDrawAllLayers(frame);
2318 EXPECT_FALSE(layer->will_draw_called());
2319 EXPECT_FALSE(layer->did_draw_called());
2321 EXPECT_TRUE(layer->visible_layer_rect().IsEmpty());
2323 // Ensure visible_layer_rect for layer is not empty
2324 layer->SetPosition(gfx::PointF());
2326 EXPECT_FALSE(layer->will_draw_called());
2327 EXPECT_FALSE(layer->did_draw_called());
2329 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2330 host_impl_->DrawLayers(&frame);
2331 host_impl_->DidDrawAllLayers(frame);
2333 EXPECT_TRUE(layer->will_draw_called());
2334 EXPECT_TRUE(layer->did_draw_called());
2336 EXPECT_FALSE(layer->visible_layer_rect().IsEmpty());
2339 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
2340 gfx::Size big_size(1000, 1000);
2341 host_impl_->SetViewportSize(big_size);
2343 host_impl_->active_tree()->SetRootLayer(
2344 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2345 DidDrawCheckLayer* root =
2346 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2348 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2349 DidDrawCheckLayer* occluded_layer =
2350 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2352 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2353 root->SetHasRenderSurface(true);
2354 DidDrawCheckLayer* top_layer =
2355 static_cast<DidDrawCheckLayer*>(root->children()[1]);
2356 // This layer covers the occluded_layer above. Make this layer large so it can
2357 // occlude.
2358 top_layer->SetBounds(big_size);
2359 top_layer->SetContentsOpaque(true);
2361 LayerTreeHostImpl::FrameData frame;
2363 EXPECT_FALSE(occluded_layer->will_draw_called());
2364 EXPECT_FALSE(occluded_layer->did_draw_called());
2365 EXPECT_FALSE(top_layer->will_draw_called());
2366 EXPECT_FALSE(top_layer->did_draw_called());
2368 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2369 host_impl_->DrawLayers(&frame);
2370 host_impl_->DidDrawAllLayers(frame);
2372 EXPECT_FALSE(occluded_layer->will_draw_called());
2373 EXPECT_FALSE(occluded_layer->did_draw_called());
2374 EXPECT_TRUE(top_layer->will_draw_called());
2375 EXPECT_TRUE(top_layer->did_draw_called());
2378 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
2379 host_impl_->active_tree()->SetRootLayer(
2380 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2381 DidDrawCheckLayer* root =
2382 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2384 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2385 root->SetHasRenderSurface(true);
2386 DidDrawCheckLayer* layer1 =
2387 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2389 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2390 DidDrawCheckLayer* layer2 =
2391 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
2393 layer1->SetHasRenderSurface(true);
2394 layer1->SetShouldFlattenTransform(true);
2396 EXPECT_FALSE(root->did_draw_called());
2397 EXPECT_FALSE(layer1->did_draw_called());
2398 EXPECT_FALSE(layer2->did_draw_called());
2400 LayerTreeHostImpl::FrameData frame;
2401 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2402 host_impl_->active_tree()->root_layer());
2403 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2404 host_impl_->DrawLayers(&frame);
2405 host_impl_->DidDrawAllLayers(frame);
2407 EXPECT_TRUE(root->did_draw_called());
2408 EXPECT_TRUE(layer1->did_draw_called());
2409 EXPECT_TRUE(layer2->did_draw_called());
2411 EXPECT_NE(root->render_surface(), layer1->render_surface());
2412 EXPECT_TRUE(layer1->render_surface());
2415 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
2416 public:
2417 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2418 int id,
2419 bool tile_missing,
2420 bool had_incomplete_tile,
2421 bool animating,
2422 ResourceProvider* resource_provider) {
2423 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
2425 tile_missing,
2426 had_incomplete_tile,
2427 animating,
2428 resource_provider));
2431 void AppendQuads(RenderPass* render_pass,
2432 AppendQuadsData* append_quads_data) override {
2433 LayerImpl::AppendQuads(render_pass, append_quads_data);
2434 if (had_incomplete_tile_)
2435 append_quads_data->num_incomplete_tiles++;
2436 if (tile_missing_)
2437 append_quads_data->num_missing_tiles++;
2440 private:
2441 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
2442 int id,
2443 bool tile_missing,
2444 bool had_incomplete_tile,
2445 bool animating,
2446 ResourceProvider* resource_provider)
2447 : DidDrawCheckLayer(tree_impl, id),
2448 tile_missing_(tile_missing),
2449 had_incomplete_tile_(had_incomplete_tile) {
2450 if (animating)
2451 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2454 bool tile_missing_;
2455 bool had_incomplete_tile_;
2458 struct PrepareToDrawSuccessTestCase {
2459 struct State {
2460 bool has_missing_tile = false;
2461 bool has_incomplete_tile = false;
2462 bool is_animating = false;
2463 bool has_copy_request = false;
2465 bool high_res_required = false;
2466 State layer_before;
2467 State layer_between;
2468 State layer_after;
2469 DrawResult expected_result;
2471 explicit PrepareToDrawSuccessTestCase(DrawResult result)
2472 : expected_result(result) {}
2475 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
2476 std::vector<PrepareToDrawSuccessTestCase> cases;
2478 // 0. Default case.
2479 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2480 // 1. Animated layer first.
2481 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2482 cases.back().layer_before.is_animating = true;
2483 // 2. Animated layer between.
2484 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2485 cases.back().layer_between.is_animating = true;
2486 // 3. Animated layer last.
2487 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2488 cases.back().layer_after.is_animating = true;
2489 // 4. Missing tile first.
2490 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2491 cases.back().layer_before.has_missing_tile = true;
2492 // 5. Missing tile between.
2493 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2494 cases.back().layer_between.has_missing_tile = true;
2495 // 6. Missing tile last.
2496 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2497 cases.back().layer_after.has_missing_tile = true;
2498 // 7. Incomplete tile first.
2499 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2500 cases.back().layer_before.has_incomplete_tile = true;
2501 // 8. Incomplete tile between.
2502 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2503 cases.back().layer_between.has_incomplete_tile = true;
2504 // 9. Incomplete tile last.
2505 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2506 cases.back().layer_after.has_incomplete_tile = true;
2507 // 10. Animation with missing tile.
2508 cases.push_back(
2509 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
2510 cases.back().layer_between.has_missing_tile = true;
2511 cases.back().layer_between.is_animating = true;
2512 // 11. Animation with incomplete tile.
2513 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2514 cases.back().layer_between.has_incomplete_tile = true;
2515 cases.back().layer_between.is_animating = true;
2517 // 12. High res required.
2518 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2519 cases.back().high_res_required = true;
2520 // 13. High res required with incomplete tile.
2521 cases.push_back(
2522 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2523 cases.back().high_res_required = true;
2524 cases.back().layer_between.has_incomplete_tile = true;
2525 // 14. High res required with missing tile.
2526 cases.push_back(
2527 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2528 cases.back().high_res_required = true;
2529 cases.back().layer_between.has_missing_tile = true;
2531 // 15. High res required is higher priority than animating missing tiles.
2532 cases.push_back(
2533 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2534 cases.back().high_res_required = true;
2535 cases.back().layer_between.has_missing_tile = true;
2536 cases.back().layer_after.has_missing_tile = true;
2537 cases.back().layer_after.is_animating = true;
2538 // 16. High res required is higher priority than animating missing tiles.
2539 cases.push_back(
2540 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2541 cases.back().high_res_required = true;
2542 cases.back().layer_between.has_missing_tile = true;
2543 cases.back().layer_before.has_missing_tile = true;
2544 cases.back().layer_before.is_animating = true;
2546 host_impl_->active_tree()->SetRootLayer(
2547 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2548 DidDrawCheckLayer* root =
2549 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2550 root->SetHasRenderSurface(true);
2552 LayerTreeHostImpl::FrameData frame;
2553 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2554 host_impl_->DrawLayers(&frame);
2555 host_impl_->DidDrawAllLayers(frame);
2556 host_impl_->SwapBuffers(frame);
2558 for (size_t i = 0; i < cases.size(); ++i) {
2559 const auto& testcase = cases[i];
2560 std::vector<LayerImpl*> to_remove;
2561 for (auto* child : root->children())
2562 to_remove.push_back(child);
2563 for (auto* child : to_remove)
2564 root->RemoveChild(child);
2566 std::ostringstream scope;
2567 scope << "Test case: " << i;
2568 SCOPED_TRACE(scope.str());
2570 root->AddChild(MissingTextureAnimatingLayer::Create(
2571 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2572 testcase.layer_before.has_incomplete_tile,
2573 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2574 DidDrawCheckLayer* before =
2575 static_cast<DidDrawCheckLayer*>(root->children().back());
2576 if (testcase.layer_before.has_copy_request)
2577 before->AddCopyRequest();
2579 root->AddChild(MissingTextureAnimatingLayer::Create(
2580 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2581 testcase.layer_between.has_incomplete_tile,
2582 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2583 DidDrawCheckLayer* between =
2584 static_cast<DidDrawCheckLayer*>(root->children().back());
2585 if (testcase.layer_between.has_copy_request)
2586 between->AddCopyRequest();
2588 root->AddChild(MissingTextureAnimatingLayer::Create(
2589 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2590 testcase.layer_after.has_incomplete_tile,
2591 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2592 DidDrawCheckLayer* after =
2593 static_cast<DidDrawCheckLayer*>(root->children().back());
2594 if (testcase.layer_after.has_copy_request)
2595 after->AddCopyRequest();
2597 if (testcase.high_res_required)
2598 host_impl_->SetRequiresHighResToDraw();
2600 LayerTreeHostImpl::FrameData frame;
2601 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2602 host_impl_->DrawLayers(&frame);
2603 host_impl_->DidDrawAllLayers(frame);
2604 host_impl_->SwapBuffers(frame);
2608 TEST_F(LayerTreeHostImplTest,
2609 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
2610 CreateHostImpl(DefaultSettings(),
2611 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2612 EXPECT_TRUE(host_impl_->output_surface()
2613 ->capabilities()
2614 .draw_and_swap_full_viewport_every_frame);
2616 std::vector<PrepareToDrawSuccessTestCase> cases;
2618 // 0. Default case.
2619 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2620 // 1. Animation with missing tile.
2621 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2622 cases.back().layer_between.has_missing_tile = true;
2623 cases.back().layer_between.is_animating = true;
2624 // 2. High res required with incomplete tile.
2625 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2626 cases.back().high_res_required = true;
2627 cases.back().layer_between.has_incomplete_tile = true;
2628 // 3. High res required with missing tile.
2629 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2630 cases.back().high_res_required = true;
2631 cases.back().layer_between.has_missing_tile = true;
2633 host_impl_->active_tree()->SetRootLayer(
2634 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2635 DidDrawCheckLayer* root =
2636 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2637 root->SetHasRenderSurface(true);
2639 LayerTreeHostImpl::FrameData frame;
2640 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2641 host_impl_->DrawLayers(&frame);
2642 host_impl_->DidDrawAllLayers(frame);
2643 host_impl_->SwapBuffers(frame);
2645 for (size_t i = 0; i < cases.size(); ++i) {
2646 const auto& testcase = cases[i];
2647 std::vector<LayerImpl*> to_remove;
2648 for (auto* child : root->children())
2649 to_remove.push_back(child);
2650 for (auto* child : to_remove)
2651 root->RemoveChild(child);
2653 std::ostringstream scope;
2654 scope << "Test case: " << i;
2655 SCOPED_TRACE(scope.str());
2657 root->AddChild(MissingTextureAnimatingLayer::Create(
2658 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2659 testcase.layer_before.has_incomplete_tile,
2660 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2661 DidDrawCheckLayer* before =
2662 static_cast<DidDrawCheckLayer*>(root->children().back());
2663 if (testcase.layer_before.has_copy_request)
2664 before->AddCopyRequest();
2666 root->AddChild(MissingTextureAnimatingLayer::Create(
2667 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2668 testcase.layer_between.has_incomplete_tile,
2669 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2670 DidDrawCheckLayer* between =
2671 static_cast<DidDrawCheckLayer*>(root->children().back());
2672 if (testcase.layer_between.has_copy_request)
2673 between->AddCopyRequest();
2675 root->AddChild(MissingTextureAnimatingLayer::Create(
2676 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2677 testcase.layer_after.has_incomplete_tile,
2678 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2679 DidDrawCheckLayer* after =
2680 static_cast<DidDrawCheckLayer*>(root->children().back());
2681 if (testcase.layer_after.has_copy_request)
2682 after->AddCopyRequest();
2684 if (testcase.high_res_required)
2685 host_impl_->SetRequiresHighResToDraw();
2687 LayerTreeHostImpl::FrameData frame;
2688 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2689 host_impl_->DrawLayers(&frame);
2690 host_impl_->DidDrawAllLayers(frame);
2691 host_impl_->SwapBuffers(frame);
2695 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2696 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2697 root->SetScrollClipLayer(Layer::INVALID_ID);
2698 root->SetHasRenderSurface(true);
2699 host_impl_->active_tree()->SetRootLayer(root.Pass());
2700 DrawFrame();
2702 // Scroll event is ignored because layer is not scrollable.
2703 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
2704 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2705 EXPECT_FALSE(did_request_redraw_);
2706 EXPECT_FALSE(did_request_commit_);
2709 // TODO(bokan): Convert these tests to create inner and outer viewports.
2710 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2711 public:
2712 LayerTreeHostImplTopControlsTest()
2713 // Make the clip size the same as the layer (content) size so the layer is
2714 // non-scrollable.
2715 : layer_size_(10, 10),
2716 clip_size_(layer_size_),
2717 top_controls_height_(50) {
2718 viewport_size_ = gfx::Size(clip_size_.width(),
2719 clip_size_.height() + top_controls_height_);
2722 bool CreateHostImpl(const LayerTreeSettings& settings,
2723 scoped_ptr<OutputSurface> output_surface) override {
2724 bool init =
2725 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
2726 if (init) {
2727 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
2728 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2730 return init;
2733 void SetupTopControlsAndScrollLayer() {
2734 scoped_ptr<LayerImpl> root =
2735 LayerImpl::Create(host_impl_->active_tree(), 1);
2736 scoped_ptr<LayerImpl> root_clip =
2737 LayerImpl::Create(host_impl_->active_tree(), 2);
2738 root_clip->SetBounds(clip_size_);
2739 root->SetScrollClipLayer(root_clip->id());
2740 root->SetBounds(layer_size_);
2741 root->SetPosition(gfx::PointF());
2742 root->SetDrawsContent(false);
2743 root->SetIsContainerForFixedPositionLayers(true);
2744 int inner_viewport_scroll_layer_id = root->id();
2745 int page_scale_layer_id = root_clip->id();
2746 root_clip->SetHasRenderSurface(true);
2747 root_clip->AddChild(root.Pass());
2748 root_clip->SetHasRenderSurface(true);
2749 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2750 host_impl_->active_tree()->SetViewportLayersFromIds(
2751 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2752 Layer::INVALID_ID);
2753 // Set a viewport size that is large enough to contain both the top controls
2754 // and some content.
2755 host_impl_->SetViewportSize(viewport_size_);
2756 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2758 host_impl_->DidChangeTopControlsPosition();
2760 host_impl_->CreatePendingTree();
2761 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2762 root =
2763 LayerImpl::Create(host_impl_->sync_tree(), 1);
2764 root_clip =
2765 LayerImpl::Create(host_impl_->sync_tree(), 2);
2766 root_clip->SetBounds(clip_size_);
2767 root->SetScrollClipLayer(root_clip->id());
2768 root->SetBounds(layer_size_);
2769 root->SetPosition(gfx::PointF());
2770 root->SetDrawsContent(false);
2771 root->SetIsContainerForFixedPositionLayers(true);
2772 inner_viewport_scroll_layer_id = root->id();
2773 page_scale_layer_id = root_clip->id();
2774 root_clip->AddChild(root.Pass());
2775 host_impl_->sync_tree()->SetRootLayer(root_clip.Pass());
2776 host_impl_->sync_tree()->SetViewportLayersFromIds(
2777 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2778 Layer::INVALID_ID);
2779 // Set a viewport size that is large enough to contain both the top controls
2780 // and some content.
2781 host_impl_->SetViewportSize(viewport_size_);
2782 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2783 host_impl_->DidChangeTopControlsPosition();
2786 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2787 const gfx::Size& inner_viewport_size,
2788 const gfx::Size& outer_viewport_size,
2789 const gfx::Size& scroll_layer_size) {
2790 CreateHostImpl(settings_, CreateOutputSurface());
2791 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2792 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2793 host_impl_->DidChangeTopControlsPosition();
2795 scoped_ptr<LayerImpl> root =
2796 LayerImpl::Create(host_impl_->active_tree(), 1);
2797 scoped_ptr<LayerImpl> root_clip =
2798 LayerImpl::Create(host_impl_->active_tree(), 2);
2799 scoped_ptr<LayerImpl> page_scale =
2800 LayerImpl::Create(host_impl_->active_tree(), 3);
2802 scoped_ptr<LayerImpl> outer_scroll =
2803 LayerImpl::Create(host_impl_->active_tree(), 4);
2804 scoped_ptr<LayerImpl> outer_clip =
2805 LayerImpl::Create(host_impl_->active_tree(), 5);
2807 root_clip->SetBounds(inner_viewport_size);
2808 root->SetScrollClipLayer(root_clip->id());
2809 root->SetBounds(outer_viewport_size);
2810 root->SetPosition(gfx::PointF());
2811 root->SetDrawsContent(false);
2812 root->SetIsContainerForFixedPositionLayers(true);
2813 root_clip->SetHasRenderSurface(true);
2814 outer_clip->SetBounds(outer_viewport_size);
2815 outer_scroll->SetScrollClipLayer(outer_clip->id());
2816 outer_scroll->SetBounds(scroll_layer_size);
2817 outer_scroll->SetPosition(gfx::PointF());
2818 outer_scroll->SetDrawsContent(false);
2819 outer_scroll->SetIsContainerForFixedPositionLayers(true);
2821 int inner_viewport_scroll_layer_id = root->id();
2822 int outer_viewport_scroll_layer_id = outer_scroll->id();
2823 int page_scale_layer_id = page_scale->id();
2825 outer_clip->AddChild(outer_scroll.Pass());
2826 root->AddChild(outer_clip.Pass());
2827 page_scale->AddChild(root.Pass());
2828 root_clip->AddChild(page_scale.Pass());
2830 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2831 host_impl_->active_tree()->SetViewportLayersFromIds(
2832 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2833 outer_viewport_scroll_layer_id);
2835 host_impl_->SetViewportSize(inner_viewport_size);
2836 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2837 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
2840 protected:
2841 gfx::Size layer_size_;
2842 gfx::Size clip_size_;
2843 gfx::Size viewport_size_;
2844 float top_controls_height_;
2846 LayerTreeSettings settings_;
2847 }; // class LayerTreeHostImplTopControlsTest
2849 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2850 SetupTopControlsAndScrollLayerWithVirtualViewport(
2851 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2852 DrawFrame();
2854 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2855 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2857 // Make the test scroll delta a fractional amount, to verify that the
2858 // fixed container size delta is (1) non-zero, and (2) fractional, and
2859 // (3) matches the movement of the top controls.
2860 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2861 host_impl_->top_controls_manager()->ScrollBegin();
2862 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2863 host_impl_->top_controls_manager()->ScrollEnd();
2865 LayerImpl* inner_viewport_scroll_layer =
2866 host_impl_->active_tree()->InnerViewportScrollLayer();
2867 DCHECK(inner_viewport_scroll_layer);
2868 host_impl_->ScrollEnd();
2869 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
2870 inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
2873 // In this test, the outer viewport is initially unscrollable. We test that a
2874 // scroll initiated on the inner viewport, causing the top controls to show and
2875 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2876 TEST_F(LayerTreeHostImplTopControlsTest,
2877 TopControlsOuterViewportBecomesScrollable) {
2878 SetupTopControlsAndScrollLayerWithVirtualViewport(
2879 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2880 DrawFrame();
2882 LayerImpl* inner_scroll =
2883 host_impl_->active_tree()->InnerViewportScrollLayer();
2884 LayerImpl* inner_container =
2885 host_impl_->active_tree()->InnerViewportContainerLayer();
2886 LayerImpl* outer_scroll =
2887 host_impl_->active_tree()->OuterViewportScrollLayer();
2888 LayerImpl* outer_container =
2889 host_impl_->active_tree()->OuterViewportContainerLayer();
2891 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2892 outer_scroll->SetDrawsContent(true);
2893 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
2895 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2896 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2897 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
2899 // The entire scroll delta should have been used to hide the top controls.
2900 // The viewport layers should be resized back to their full sizes.
2901 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2902 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2903 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
2904 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
2906 // The inner viewport should be scrollable by 50px * page_scale.
2907 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
2908 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
2909 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2910 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
2912 host_impl_->ScrollEnd();
2914 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2915 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2916 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
2918 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2920 // The entire scroll delta should have been used to show the top controls.
2921 // The outer viewport should be resized to accomodate and scrolled to the
2922 // bottom of the document to keep the viewport in place.
2923 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2924 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
2925 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
2926 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
2927 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2929 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2930 // since it wasn't scrollable when the scroll began.
2931 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
2932 EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
2933 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2935 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
2936 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2937 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2939 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2940 host_impl_->ScrollEnd();
2942 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2943 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2946 // Test that the fixed position container delta is appropriately adjusted
2947 // by the top controls showing/hiding and page scale doesn't affect it.
2948 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
2949 SetupTopControlsAndScrollLayerWithVirtualViewport(
2950 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2951 DrawFrame();
2953 float page_scale = 1.5f;
2954 LayerImpl* outer_viewport_scroll_layer =
2955 host_impl_->active_tree()->OuterViewportScrollLayer();
2957 // Zoom in, since the fixed container is the outer viewport, the delta should
2958 // not be scaled.
2959 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
2961 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2962 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2964 // Scroll down, the top controls hiding should expand the viewport size so
2965 // the delta should be equal to the scroll distance.
2966 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
2967 host_impl_->top_controls_manager()->ScrollBegin();
2968 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2969 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
2970 host_impl_->top_controls_manager()->ContentTopOffset());
2971 EXPECT_VECTOR_EQ(top_controls_scroll_delta,
2972 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2973 host_impl_->ScrollEnd();
2975 // Scroll past the maximum extent. The delta shouldn't be greater than the
2976 // top controls height.
2977 host_impl_->top_controls_manager()->ScrollBegin();
2978 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2979 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2980 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2981 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2982 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
2983 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2984 host_impl_->ScrollEnd();
2986 // Scroll in the direction to make the top controls show.
2987 host_impl_->top_controls_manager()->ScrollBegin();
2988 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
2989 EXPECT_EQ(top_controls_scroll_delta.y(),
2990 host_impl_->top_controls_manager()->ContentTopOffset());
2991 EXPECT_VECTOR_EQ(
2992 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
2993 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2994 host_impl_->top_controls_manager()->ScrollEnd();
2997 // Test that if only the top controls are scrolled, we shouldn't request a
2998 // commit.
2999 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsDontTriggerCommit) {
3000 SetupTopControlsAndScrollLayerWithVirtualViewport(
3001 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3002 DrawFrame();
3004 // Show top controls
3005 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3007 // Scroll 25px to hide top controls
3008 gfx::Vector2dF scroll_delta(0.f, 25.f);
3009 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3010 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3011 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3012 EXPECT_FALSE(did_request_commit_);
3015 // Test that if a scrollable sublayer doesn't consume the scroll,
3016 // top controls should hide when scrolling down.
3017 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
3018 gfx::Size sub_content_size(100, 400);
3019 gfx::Size sub_content_layer_size(100, 300);
3020 SetupTopControlsAndScrollLayerWithVirtualViewport(
3021 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3022 DrawFrame();
3024 // Show top controls
3025 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3027 LayerImpl* outer_viewport_scroll_layer =
3028 host_impl_->active_tree()->OuterViewportScrollLayer();
3029 int id = outer_viewport_scroll_layer->id();
3031 scoped_ptr<LayerImpl> child =
3032 LayerImpl::Create(host_impl_->active_tree(), id + 2);
3033 scoped_ptr<LayerImpl> child_clip =
3034 LayerImpl::Create(host_impl_->active_tree(), id + 3);
3036 child_clip->SetBounds(sub_content_layer_size);
3037 child->SetScrollClipLayer(child_clip->id());
3038 child->SetBounds(sub_content_size);
3039 child->SetPosition(gfx::PointF());
3040 child->SetDrawsContent(true);
3041 child->SetIsContainerForFixedPositionLayers(true);
3043 // scroll child to limit
3044 child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
3045 child_clip->AddChild(child.Pass());
3046 outer_viewport_scroll_layer->AddChild(child_clip.Pass());
3048 // Scroll 25px to hide top controls
3049 gfx::Vector2dF scroll_delta(0.f, 25.f);
3050 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3051 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3052 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3053 host_impl_->ScrollEnd();
3055 // Top controls should be hidden
3056 EXPECT_EQ(scroll_delta.y(),
3057 top_controls_height_ -
3058 host_impl_->top_controls_manager()->ContentTopOffset());
3061 // Ensure setting the top controls position explicitly using the setters on the
3062 // TreeImpl correctly affects the top controls manager and viewport bounds.
3063 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
3064 CreateHostImpl(settings_, CreateOutputSurface());
3065 SetupTopControlsAndScrollLayer();
3066 DrawFrame();
3068 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3069 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3070 30.f / top_controls_height_);
3071 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3072 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
3073 EXPECT_FLOAT_EQ(-20.f,
3074 host_impl_->top_controls_manager()->ControlsTopOffset());
3076 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3077 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3078 EXPECT_FLOAT_EQ(-50.f,
3079 host_impl_->top_controls_manager()->ControlsTopOffset());
3081 host_impl_->DidChangeTopControlsPosition();
3083 // Now that top controls have moved, expect the clip to resize.
3084 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3085 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3088 // Test that the top_controls delta and sent delta are appropriately
3089 // applied on sync tree activation. The total top controls offset shouldn't
3090 // change after the activation.
3091 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
3092 CreateHostImpl(settings_, CreateOutputSurface());
3093 SetupTopControlsAndScrollLayer();
3094 DrawFrame();
3096 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3097 20.f / top_controls_height_);
3098 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3099 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
3100 15.f / top_controls_height_);
3101 host_impl_->active_tree()
3102 ->top_controls_shown_ratio()
3103 ->PullDeltaForMainThread();
3104 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3105 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
3106 top_controls_height_);
3108 host_impl_->DidChangeTopControlsPosition();
3109 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3110 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3111 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3113 host_impl_->ActivateSyncTree();
3115 root_clip_ptr = host_impl_->active_tree()->root_layer();
3116 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3117 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3119 EXPECT_FLOAT_EQ(
3120 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
3121 top_controls_height_);
3122 EXPECT_FLOAT_EQ(
3123 15.f,
3124 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3125 top_controls_height_);
3128 // Test that changing the top controls layout height is correctly applied to
3129 // the inner viewport container bounds. That is, the top controls layout
3130 // height is the amount that the inner viewport container was shrunk outside
3131 // the compositor to accommodate the top controls.
3132 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
3133 CreateHostImpl(settings_, CreateOutputSurface());
3134 SetupTopControlsAndScrollLayer();
3135 DrawFrame();
3137 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
3138 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
3140 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3141 1.f);
3142 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3143 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3145 host_impl_->DidChangeTopControlsPosition();
3146 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3147 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3148 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3150 host_impl_->sync_tree()->root_layer()->SetBounds(
3151 gfx::Size(root_clip_ptr->bounds().width(),
3152 root_clip_ptr->bounds().height() - 50.f));
3154 host_impl_->ActivateSyncTree();
3156 root_clip_ptr = host_impl_->active_tree()->root_layer();
3157 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3159 // The total bounds should remain unchanged since the bounds delta should
3160 // account for the difference between the layout height and the current
3161 // top controls offset.
3162 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3163 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), root_clip_ptr->bounds_delta());
3165 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
3166 host_impl_->DidChangeTopControlsPosition();
3168 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
3169 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
3170 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
3171 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), root_clip_ptr->bounds_delta());
3172 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
3173 root_clip_ptr->bounds());
3176 // Test that showing/hiding the top controls when the viewport is fully scrolled
3177 // doesn't incorrectly change the viewport offset due to clamping from changing
3178 // viewport bounds.
3179 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
3180 SetupTopControlsAndScrollLayerWithVirtualViewport(
3181 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3182 DrawFrame();
3184 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3186 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
3187 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
3189 // Scroll the viewports to max scroll offset.
3190 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3191 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3193 gfx::ScrollOffset viewport_offset =
3194 host_impl_->active_tree()->TotalScrollOffset();
3195 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
3197 // Hide the top controls by 25px.
3198 gfx::Vector2dF scroll_delta(0.f, 25.f);
3199 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3200 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3201 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3203 // scrolling down at the max extents no longer hides the top controls
3204 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3206 // forcefully hide the top controls by 25px
3207 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
3208 host_impl_->ScrollEnd();
3210 EXPECT_FLOAT_EQ(scroll_delta.y(),
3211 top_controls_height_ -
3212 host_impl_->top_controls_manager()->ContentTopOffset());
3214 inner_scroll->ClampScrollToMaxScrollOffset();
3215 outer_scroll->ClampScrollToMaxScrollOffset();
3217 // We should still be fully scrolled.
3218 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3219 host_impl_->active_tree()->TotalScrollOffset());
3221 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
3223 // Bring the top controls down by 25px.
3224 scroll_delta = gfx::Vector2dF(0.f, -25.f);
3225 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3226 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3227 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3228 host_impl_->ScrollEnd();
3230 // The viewport offset shouldn't have changed.
3231 EXPECT_EQ(viewport_offset,
3232 host_impl_->active_tree()->TotalScrollOffset());
3234 // Scroll the viewports to max scroll offset.
3235 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3236 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3237 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3238 host_impl_->active_tree()->TotalScrollOffset());
3241 // Test that the top controls coming in and out maintains the same aspect ratio
3242 // between the inner and outer viewports.
3243 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
3244 SetupTopControlsAndScrollLayerWithVirtualViewport(
3245 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3246 DrawFrame();
3248 EXPECT_FLOAT_EQ(top_controls_height_,
3249 host_impl_->top_controls_manager()->ContentTopOffset());
3251 gfx::Vector2dF scroll_delta(0.f, 25.f);
3252 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3253 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3254 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3255 host_impl_->ScrollEnd();
3257 EXPECT_FLOAT_EQ(scroll_delta.y(),
3258 top_controls_height_ -
3259 host_impl_->top_controls_manager()->ContentTopOffset());
3261 // Top controls were hidden by 25px so the inner viewport should have expanded
3262 // by that much.
3263 LayerImpl* outer_container =
3264 host_impl_->active_tree()->OuterViewportContainerLayer();
3265 LayerImpl* inner_container =
3266 host_impl_->active_tree()->InnerViewportContainerLayer();
3267 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
3269 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3270 float aspect_ratio = inner_container->BoundsForScrolling().width() /
3271 inner_container->BoundsForScrolling().height();
3272 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
3273 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
3274 EXPECT_EQ(expected,
3275 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
3278 // Test that scrolling the outer viewport affects the top controls.
3279 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
3280 SetupTopControlsAndScrollLayerWithVirtualViewport(
3281 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3282 DrawFrame();
3284 EXPECT_EQ(top_controls_height_,
3285 host_impl_->top_controls_manager()->ContentTopOffset());
3287 // Send a gesture scroll that will scroll the outer viewport, make sure the
3288 // top controls get scrolled.
3289 gfx::Vector2dF scroll_delta(0.f, 15.f);
3290 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3291 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3292 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3293 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3294 host_impl_->CurrentlyScrollingLayer());
3295 host_impl_->ScrollEnd();
3297 EXPECT_FLOAT_EQ(scroll_delta.y(),
3298 top_controls_height_ -
3299 host_impl_->top_controls_manager()->ContentTopOffset());
3301 scroll_delta = gfx::Vector2dF(0.f, 50.f);
3302 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3303 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3304 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3306 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
3307 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3308 host_impl_->CurrentlyScrollingLayer());
3310 host_impl_->ScrollEnd();
3312 // Position the viewports such that the inner viewport will be scrolled.
3313 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
3314 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3315 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
3317 scroll_delta = gfx::Vector2dF(0.f, -65.f);
3318 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3319 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3320 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3322 EXPECT_EQ(top_controls_height_,
3323 host_impl_->top_controls_manager()->ContentTopOffset());
3324 EXPECT_FLOAT_EQ(
3325 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
3326 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
3328 host_impl_->ScrollEnd();
3331 TEST_F(LayerTreeHostImplTopControlsTest,
3332 ScrollNonScrollableRootWithTopControls) {
3333 CreateHostImpl(settings_, CreateOutputSurface());
3334 SetupTopControlsAndScrollLayer();
3335 DrawFrame();
3337 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3338 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3340 host_impl_->top_controls_manager()->ScrollBegin();
3341 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
3342 host_impl_->top_controls_manager()->ScrollEnd();
3343 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3344 // Now that top controls have moved, expect the clip to resize.
3345 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
3346 EXPECT_EQ(viewport_size_, root_clip_ptr->bounds());
3348 host_impl_->ScrollEnd();
3350 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3351 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3353 float scroll_increment_y = -25.f;
3354 host_impl_->top_controls_manager()->ScrollBegin();
3355 host_impl_->top_controls_manager()->ScrollBy(
3356 gfx::Vector2dF(0.f, scroll_increment_y));
3357 EXPECT_FLOAT_EQ(-scroll_increment_y,
3358 host_impl_->top_controls_manager()->ContentTopOffset());
3359 // Now that top controls have moved, expect the clip to resize.
3360 EXPECT_EQ(gfx::Size(viewport_size_.width(),
3361 viewport_size_.height() + scroll_increment_y),
3362 root_clip_ptr->bounds());
3364 host_impl_->top_controls_manager()->ScrollBy(
3365 gfx::Vector2dF(0.f, scroll_increment_y));
3366 host_impl_->top_controls_manager()->ScrollEnd();
3367 EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
3368 host_impl_->top_controls_manager()->ContentTopOffset());
3369 // Now that top controls have moved, expect the clip to resize.
3370 EXPECT_EQ(clip_size_, root_clip_ptr->bounds());
3372 host_impl_->ScrollEnd();
3374 // Verify the layer is once-again non-scrollable.
3375 EXPECT_EQ(
3376 gfx::ScrollOffset(),
3377 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3379 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3380 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3383 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
3384 // Test the configuration where a non-composited root layer is embedded in a
3385 // scrollable outer layer.
3386 gfx::Size surface_size(10, 10);
3387 gfx::Size contents_size(20, 20);
3389 scoped_ptr<LayerImpl> content_layer =
3390 LayerImpl::Create(host_impl_->active_tree(), 1);
3391 content_layer->SetDrawsContent(true);
3392 content_layer->SetPosition(gfx::PointF());
3393 content_layer->SetBounds(contents_size);
3395 scoped_ptr<LayerImpl> scroll_clip_layer =
3396 LayerImpl::Create(host_impl_->active_tree(), 3);
3397 scroll_clip_layer->SetBounds(surface_size);
3399 scoped_ptr<LayerImpl> scroll_layer =
3400 LayerImpl::Create(host_impl_->active_tree(), 2);
3401 scroll_layer->SetScrollClipLayer(3);
3402 scroll_layer->SetBounds(contents_size);
3403 scroll_layer->SetPosition(gfx::PointF());
3404 scroll_layer->AddChild(content_layer.Pass());
3405 scroll_clip_layer->AddChild(scroll_layer.Pass());
3407 scroll_clip_layer->SetHasRenderSurface(true);
3408 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
3409 host_impl_->SetViewportSize(surface_size);
3410 DrawFrame();
3412 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3413 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3414 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3415 host_impl_->ScrollEnd();
3416 EXPECT_TRUE(did_request_redraw_);
3417 EXPECT_TRUE(did_request_commit_);
3420 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
3421 gfx::Size surface_size(10, 10);
3422 gfx::Size contents_size(20, 20);
3423 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3424 root->SetBounds(surface_size);
3425 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
3426 root->SetHasRenderSurface(true);
3427 host_impl_->active_tree()->SetRootLayer(root.Pass());
3428 host_impl_->SetViewportSize(surface_size);
3429 DrawFrame();
3431 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3432 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3433 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3434 host_impl_->ScrollEnd();
3435 EXPECT_TRUE(did_request_redraw_);
3436 EXPECT_TRUE(did_request_commit_);
3439 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
3440 gfx::Size surface_size(10, 10);
3441 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3442 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
3443 root->SetHasRenderSurface(true);
3444 host_impl_->active_tree()->SetRootLayer(root.Pass());
3445 host_impl_->SetViewportSize(surface_size);
3446 DrawFrame();
3448 // Scroll event is ignored because the input coordinate is outside the layer
3449 // boundaries.
3450 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3451 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
3452 EXPECT_FALSE(did_request_redraw_);
3453 EXPECT_FALSE(did_request_commit_);
3456 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
3457 gfx::Size surface_size(10, 10);
3458 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3459 root->SetHasRenderSurface(true);
3460 scoped_ptr<LayerImpl> child =
3461 CreateScrollableLayer(2, surface_size, root.get());
3462 host_impl_->SetViewportSize(surface_size);
3464 gfx::Transform matrix;
3465 matrix.RotateAboutXAxis(180.0);
3466 child->SetTransform(matrix);
3467 child->SetDoubleSided(false);
3469 root->AddChild(child.Pass());
3470 host_impl_->active_tree()->SetRootLayer(root.Pass());
3471 DrawFrame();
3473 // Scroll event is ignored because the scrollable layer is not facing the
3474 // viewer and there is nothing scrollable behind it.
3475 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3476 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3477 EXPECT_FALSE(did_request_redraw_);
3478 EXPECT_FALSE(did_request_commit_);
3481 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
3482 gfx::Size surface_size(10, 10);
3483 scoped_ptr<LayerImpl> clip_layer =
3484 LayerImpl::Create(host_impl_->active_tree(), 3);
3485 scoped_ptr<LayerImpl> content_layer =
3486 CreateScrollableLayer(1, surface_size, clip_layer.get());
3487 content_layer->SetShouldScrollOnMainThread(true);
3488 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
3490 // Note: we can use the same clip layer for both since both calls to
3491 // CreateScrollableLayer() use the same surface size.
3492 scoped_ptr<LayerImpl> scroll_layer =
3493 CreateScrollableLayer(2, surface_size, clip_layer.get());
3494 scroll_layer->AddChild(content_layer.Pass());
3495 clip_layer->AddChild(scroll_layer.Pass());
3496 clip_layer->SetHasRenderSurface(true);
3498 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
3499 host_impl_->SetViewportSize(surface_size);
3500 DrawFrame();
3502 // Scrolling fails because the content layer is asking to be scrolled on the
3503 // main thread.
3504 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
3505 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3508 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
3509 gfx::Size surface_size(20, 20);
3510 gfx::Size viewport_size(10, 10);
3511 float page_scale = 2.f;
3512 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3513 scoped_ptr<LayerImpl> root_clip =
3514 LayerImpl::Create(host_impl_->active_tree(), 2);
3515 scoped_ptr<LayerImpl> root_scrolling =
3516 CreateScrollableLayer(3, surface_size, root_clip.get());
3517 EXPECT_EQ(viewport_size, root_clip->bounds());
3518 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3519 root_clip->AddChild(root_scrolling.Pass());
3520 root->AddChild(root_clip.Pass());
3521 root->SetHasRenderSurface(true);
3522 host_impl_->active_tree()->SetRootLayer(root.Pass());
3523 // The behaviour in this test assumes the page scale is applied at a layer
3524 // above the clip layer.
3525 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3526 Layer::INVALID_ID);
3527 host_impl_->active_tree()->DidBecomeActive();
3528 host_impl_->SetViewportSize(viewport_size);
3529 DrawFrame();
3531 LayerImpl* root_scroll =
3532 host_impl_->active_tree()->InnerViewportScrollLayer();
3533 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3535 gfx::Vector2d scroll_delta(0, 10);
3536 gfx::Vector2d expected_scroll_delta = scroll_delta;
3537 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3538 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3539 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3540 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3541 host_impl_->ScrollEnd();
3543 // Set new page scale from main thread.
3544 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, page_scale,
3545 page_scale);
3547 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3548 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
3549 expected_scroll_delta));
3551 // The scroll range should also have been updated.
3552 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3554 // The page scale delta remains constant because the impl thread did not
3555 // scale.
3556 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3559 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3560 gfx::Size surface_size(20, 20);
3561 gfx::Size viewport_size(10, 10);
3562 float page_scale = 2.f;
3563 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3564 scoped_ptr<LayerImpl> root_clip =
3565 LayerImpl::Create(host_impl_->active_tree(), 2);
3566 scoped_ptr<LayerImpl> root_scrolling =
3567 CreateScrollableLayer(3, surface_size, root_clip.get());
3568 EXPECT_EQ(viewport_size, root_clip->bounds());
3569 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3570 root_clip->AddChild(root_scrolling.Pass());
3571 root->AddChild(root_clip.Pass());
3572 root->SetHasRenderSurface(true);
3573 host_impl_->active_tree()->SetRootLayer(root.Pass());
3574 // The behaviour in this test assumes the page scale is applied at a layer
3575 // above the clip layer.
3576 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 3,
3577 Layer::INVALID_ID);
3578 host_impl_->active_tree()->DidBecomeActive();
3579 host_impl_->SetViewportSize(viewport_size);
3580 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, page_scale);
3581 DrawFrame();
3583 LayerImpl* root_scroll =
3584 host_impl_->active_tree()->InnerViewportScrollLayer();
3585 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3587 gfx::Vector2d scroll_delta(0, 10);
3588 gfx::Vector2d expected_scroll_delta = scroll_delta;
3589 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3590 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3591 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3592 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3593 host_impl_->ScrollEnd();
3595 // Set new page scale on impl thread by pinching.
3596 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3597 host_impl_->PinchGestureBegin();
3598 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3599 host_impl_->PinchGestureEnd();
3600 host_impl_->ScrollEnd();
3601 DrawOneFrame();
3603 // The scroll delta is not scaled because the main thread did not scale.
3604 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3605 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
3606 expected_scroll_delta));
3608 // The scroll range should also have been updated.
3609 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3611 // The page scale delta should match the new scale on the impl side.
3612 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3615 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3616 gfx::Size surface_size(10, 10);
3617 float default_page_scale = 1.f;
3618 gfx::Transform default_page_scale_matrix;
3619 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3621 float new_page_scale = 2.f;
3622 gfx::Transform new_page_scale_matrix;
3623 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3625 // Create a normal scrollable root layer and another scrollable child layer.
3626 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3627 LayerImpl* root = host_impl_->active_tree()->root_layer();
3628 LayerImpl* child = scroll->children()[0];
3630 scoped_ptr<LayerImpl> scrollable_child_clip =
3631 LayerImpl::Create(host_impl_->active_tree(), 6);
3632 scoped_ptr<LayerImpl> scrollable_child =
3633 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3634 scrollable_child_clip->AddChild(scrollable_child.Pass());
3635 child->AddChild(scrollable_child_clip.Pass());
3636 LayerImpl* grand_child = child->children()[0];
3638 // Set new page scale on impl thread by pinching.
3639 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3640 host_impl_->PinchGestureBegin();
3641 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3642 host_impl_->PinchGestureEnd();
3643 host_impl_->ScrollEnd();
3644 DrawOneFrame();
3646 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3647 // the page scale delta on the root layer is applied hierarchically.
3648 LayerTreeHostImpl::FrameData frame;
3649 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3650 host_impl_->DrawLayers(&frame);
3651 host_impl_->DidDrawAllLayers(frame);
3653 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3654 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3655 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3656 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3657 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3658 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3659 EXPECT_EQ(new_page_scale,
3660 grand_child->draw_transform().matrix().getDouble(0, 0));
3661 EXPECT_EQ(new_page_scale,
3662 grand_child->draw_transform().matrix().getDouble(1, 1));
3665 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3666 gfx::Size surface_size(30, 30);
3667 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3668 root->SetBounds(gfx::Size(5, 5));
3669 root->SetHasRenderSurface(true);
3670 scoped_ptr<LayerImpl> root_scrolling =
3671 LayerImpl::Create(host_impl_->active_tree(), 2);
3672 root_scrolling->SetBounds(surface_size);
3673 root_scrolling->SetScrollClipLayer(root->id());
3674 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3675 LayerImpl* root_scrolling_ptr = root_scrolling.get();
3676 root->AddChild(root_scrolling.Pass());
3677 int child_scroll_layer_id = 3;
3678 scoped_ptr<LayerImpl> child_scrolling = CreateScrollableLayer(
3679 child_scroll_layer_id, surface_size, root_scrolling_ptr);
3680 LayerImpl* child = child_scrolling.get();
3681 root_scrolling_ptr->AddChild(child_scrolling.Pass());
3682 host_impl_->active_tree()->SetRootLayer(root.Pass());
3683 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3684 Layer::INVALID_ID);
3685 host_impl_->active_tree()->DidBecomeActive();
3686 host_impl_->SetViewportSize(surface_size);
3687 DrawFrame();
3689 gfx::Vector2d scroll_delta(0, 10);
3690 gfx::Vector2d expected_scroll_delta(scroll_delta);
3691 gfx::ScrollOffset expected_max_scroll(child->MaxScrollOffset());
3692 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3693 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3694 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3695 host_impl_->ScrollEnd();
3697 float page_scale = 2.f;
3698 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
3699 page_scale);
3701 DrawOneFrame();
3703 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3704 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_scroll_layer_id,
3705 expected_scroll_delta));
3707 // The scroll range should not have changed.
3708 EXPECT_EQ(child->MaxScrollOffset(), expected_max_scroll);
3710 // The page scale delta remains constant because the impl thread did not
3711 // scale.
3712 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3715 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
3716 // Scroll a child layer beyond its maximum scroll range and make sure the
3717 // parent layer is scrolled on the axis on which the child was unable to
3718 // scroll.
3719 gfx::Size surface_size(10, 10);
3720 gfx::Size content_size(20, 20);
3721 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3722 root->SetBounds(surface_size);
3723 root->SetHasRenderSurface(true);
3724 scoped_ptr<LayerImpl> grand_child =
3725 CreateScrollableLayer(3, content_size, root.get());
3727 scoped_ptr<LayerImpl> child =
3728 CreateScrollableLayer(2, content_size, root.get());
3729 LayerImpl* grand_child_layer = grand_child.get();
3730 child->AddChild(grand_child.Pass());
3732 LayerImpl* child_layer = child.get();
3733 root->AddChild(child.Pass());
3734 host_impl_->active_tree()->SetRootLayer(root.Pass());
3735 host_impl_->active_tree()->DidBecomeActive();
3736 host_impl_->SetViewportSize(surface_size);
3737 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3738 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3740 DrawFrame();
3742 gfx::Vector2d scroll_delta(-8, -7);
3743 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3744 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3745 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3746 host_impl_->ScrollEnd();
3748 scoped_ptr<ScrollAndScaleSet> scroll_info =
3749 host_impl_->ProcessScrollDeltas();
3751 // The grand child should have scrolled up to its limit.
3752 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3753 LayerImpl* grand_child = child->children()[0];
3754 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3755 gfx::Vector2d(0, -5)));
3757 // The child should have only scrolled on the other axis.
3758 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
3759 gfx::Vector2d(-3, 0)));
3763 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
3764 // Scroll a child layer beyond its maximum scroll range and make sure the
3765 // the scroll doesn't bubble up to the parent layer.
3766 gfx::Size surface_size(20, 20);
3767 gfx::Size viewport_size(10, 10);
3768 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3769 root->SetHasRenderSurface(true);
3770 scoped_ptr<LayerImpl> root_scrolling =
3771 CreateScrollableLayer(2, surface_size, root.get());
3772 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3774 scoped_ptr<LayerImpl> grand_child =
3775 CreateScrollableLayer(4, surface_size, root.get());
3777 scoped_ptr<LayerImpl> child =
3778 CreateScrollableLayer(3, surface_size, root.get());
3779 LayerImpl* grand_child_layer = grand_child.get();
3780 child->AddChild(grand_child.Pass());
3782 LayerImpl* child_layer = child.get();
3783 root_scrolling->AddChild(child.Pass());
3784 root->AddChild(root_scrolling.Pass());
3785 EXPECT_EQ(viewport_size, root->bounds());
3786 host_impl_->active_tree()->SetRootLayer(root.Pass());
3787 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3788 Layer::INVALID_ID);
3789 host_impl_->active_tree()->DidBecomeActive();
3790 host_impl_->SetViewportSize(viewport_size);
3792 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3793 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3795 DrawFrame();
3797 gfx::Vector2d scroll_delta(0, -10);
3798 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3799 host_impl_->ScrollBegin(gfx::Point(),
3800 InputHandler::NON_BUBBLING_GESTURE));
3801 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3802 host_impl_->ScrollEnd();
3804 scoped_ptr<ScrollAndScaleSet> scroll_info =
3805 host_impl_->ProcessScrollDeltas();
3807 // The grand child should have scrolled up to its limit.
3808 LayerImpl* child =
3809 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
3810 LayerImpl* grand_child = child->children()[0];
3811 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3812 gfx::Vector2d(0, -2)));
3814 // The child should not have scrolled.
3815 ExpectNone(*scroll_info.get(), child->id());
3817 // The next time we scroll we should only scroll the parent.
3818 scroll_delta = gfx::Vector2d(0, -3);
3819 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3820 host_impl_->ScrollBegin(gfx::Point(5, 5),
3821 InputHandler::NON_BUBBLING_GESTURE));
3822 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3823 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3824 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
3825 host_impl_->ScrollEnd();
3827 scroll_info = host_impl_->ProcessScrollDeltas();
3829 // The child should have scrolled up to its limit.
3830 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
3831 gfx::Vector2d(0, -3)));
3833 // The grand child should not have scrolled.
3834 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3835 gfx::Vector2d(0, -2)));
3837 // After scrolling the parent, another scroll on the opposite direction
3838 // should still scroll the child.
3839 scroll_delta = gfx::Vector2d(0, 7);
3840 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3841 host_impl_->ScrollBegin(gfx::Point(5, 5),
3842 InputHandler::NON_BUBBLING_GESTURE));
3843 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3844 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3845 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3846 host_impl_->ScrollEnd();
3848 scroll_info = host_impl_->ProcessScrollDeltas();
3850 // The grand child should have scrolled.
3851 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3852 gfx::Vector2d(0, 5)));
3854 // The child should not have scrolled.
3855 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
3856 gfx::Vector2d(0, -3)));
3858 // Scrolling should be adjusted from viewport space.
3859 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
3860 host_impl_->SetPageScaleOnActiveTree(2.f);
3862 scroll_delta = gfx::Vector2d(0, -2);
3863 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3864 host_impl_->ScrollBegin(gfx::Point(1, 1),
3865 InputHandler::NON_BUBBLING_GESTURE));
3866 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
3867 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3868 host_impl_->ScrollEnd();
3870 scroll_info = host_impl_->ProcessScrollDeltas();
3872 // Should have scrolled by half the amount in layer space (5 - 2/2)
3873 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3874 gfx::Vector2d(0, 4)));
3877 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
3878 // When we try to scroll a non-scrollable child layer, the scroll delta
3879 // should be applied to one of its ancestors if possible.
3880 gfx::Size surface_size(10, 10);
3881 gfx::Size content_size(20, 20);
3882 scoped_ptr<LayerImpl> root_clip =
3883 LayerImpl::Create(host_impl_->active_tree(), 3);
3884 root_clip->SetHasRenderSurface(true);
3885 scoped_ptr<LayerImpl> root =
3886 CreateScrollableLayer(1, content_size, root_clip.get());
3887 // Make 'root' the clip layer for child: since they have the same sizes the
3888 // child will have zero max_scroll_offset and scrolls will bubble.
3889 scoped_ptr<LayerImpl> child =
3890 CreateScrollableLayer(2, content_size, root.get());
3891 child->SetIsContainerForFixedPositionLayers(true);
3892 root->SetBounds(content_size);
3894 int root_scroll_id = root->id();
3895 root->AddChild(child.Pass());
3896 root_clip->AddChild(root.Pass());
3898 host_impl_->SetViewportSize(surface_size);
3899 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3900 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
3901 Layer::INVALID_ID);
3902 host_impl_->active_tree()->DidBecomeActive();
3903 DrawFrame();
3905 gfx::Vector2d scroll_delta(0, 4);
3906 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3907 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3908 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3909 host_impl_->ScrollEnd();
3911 scoped_ptr<ScrollAndScaleSet> scroll_info =
3912 host_impl_->ProcessScrollDeltas();
3914 // Only the root scroll should have scrolled.
3915 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
3916 EXPECT_TRUE(
3917 ScrollInfoContains(*scroll_info.get(), root_scroll_id, scroll_delta));
3921 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
3922 gfx::Size surface_size(10, 10);
3923 scoped_ptr<LayerImpl> root_clip =
3924 LayerImpl::Create(host_impl_->active_tree(), 1);
3925 scoped_ptr<LayerImpl> root_scroll =
3926 CreateScrollableLayer(2, surface_size, root_clip.get());
3927 root_scroll->SetIsContainerForFixedPositionLayers(true);
3928 root_clip->SetHasRenderSurface(true);
3929 root_clip->AddChild(root_scroll.Pass());
3930 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3931 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3932 Layer::INVALID_ID);
3933 host_impl_->active_tree()->DidBecomeActive();
3934 host_impl_->SetViewportSize(surface_size);
3936 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3937 // synchronization.
3938 DrawFrame();
3939 host_impl_->active_tree()->DetachLayerTree();
3940 scoped_ptr<LayerImpl> root_clip2 =
3941 LayerImpl::Create(host_impl_->active_tree(), 3);
3942 scoped_ptr<LayerImpl> root_scroll2 =
3943 CreateScrollableLayer(4, surface_size, root_clip2.get());
3944 root_scroll2->SetIsContainerForFixedPositionLayers(true);
3945 root_clip2->AddChild(root_scroll2.Pass());
3946 root_clip2->SetHasRenderSurface(true);
3947 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
3948 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
3949 Layer::INVALID_ID);
3950 host_impl_->active_tree()->DidBecomeActive();
3952 // Scrolling should still work even though we did not draw yet.
3953 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3954 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3957 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
3958 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3960 // Rotate the root layer 90 degrees counter-clockwise about its center.
3961 gfx::Transform rotate_transform;
3962 rotate_transform.Rotate(-90.0);
3963 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
3965 gfx::Size surface_size(50, 50);
3966 host_impl_->SetViewportSize(surface_size);
3967 DrawFrame();
3969 // Scroll to the right in screen coordinates with a gesture.
3970 gfx::Vector2d gesture_scroll_delta(10, 0);
3971 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3972 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3973 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3974 host_impl_->ScrollEnd();
3976 // The layer should have scrolled down in its local coordinates.
3977 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3978 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
3979 gfx::Vector2d(0, gesture_scroll_delta.x())));
3981 // Reset and scroll down with the wheel.
3982 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3983 gfx::Vector2d wheel_scroll_delta(0, 10);
3984 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3985 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3986 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3987 host_impl_->ScrollEnd();
3989 // The layer should have scrolled down in its local coordinates.
3990 scroll_info = host_impl_->ProcessScrollDeltas();
3991 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
3992 wheel_scroll_delta));
3995 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
3996 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3997 int child_clip_layer_id = 6;
3998 int child_layer_id = 7;
3999 float child_layer_angle = -20.f;
4001 // Create a child layer that is rotated to a non-axis-aligned angle.
4002 scoped_ptr<LayerImpl> clip_layer =
4003 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
4004 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
4005 child_layer_id, scroll_layer->bounds(), clip_layer.get());
4006 gfx::Transform rotate_transform;
4007 rotate_transform.Translate(-50.0, -50.0);
4008 rotate_transform.Rotate(child_layer_angle);
4009 rotate_transform.Translate(50.0, 50.0);
4010 clip_layer->SetTransform(rotate_transform);
4012 // Only allow vertical scrolling.
4013 clip_layer->SetBounds(
4014 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
4015 // The rotation depends on the layer's transform origin, and the child layer
4016 // is a different size than the clip, so make sure the clip layer's origin
4017 // lines up over the child.
4018 clip_layer->SetTransformOrigin(gfx::Point3F(
4019 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
4020 LayerImpl* child_ptr = child.get();
4021 clip_layer->AddChild(child.Pass());
4022 scroll_layer->AddChild(clip_layer.Pass());
4024 gfx::Size surface_size(50, 50);
4025 host_impl_->SetViewportSize(surface_size);
4026 DrawFrame();
4028 // Scroll down in screen coordinates with a gesture.
4029 gfx::Vector2d gesture_scroll_delta(0, 10);
4030 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4031 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4032 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4033 host_impl_->ScrollEnd();
4035 // The child layer should have scrolled down in its local coordinates an
4036 // amount proportional to the angle between it and the input scroll delta.
4037 gfx::Vector2d expected_scroll_delta(
4038 0, gesture_scroll_delta.y() *
4039 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
4040 scoped_ptr<ScrollAndScaleSet> scroll_info =
4041 host_impl_->ProcessScrollDeltas();
4042 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4043 expected_scroll_delta));
4045 // The root scroll layer should not have scrolled, because the input delta
4046 // was close to the layer's axis of movement.
4047 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4050 // Now reset and scroll the same amount horizontally.
4051 child_ptr->SetScrollDelta(gfx::Vector2dF());
4052 gfx::Vector2d gesture_scroll_delta(10, 0);
4053 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4054 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4055 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4056 host_impl_->ScrollEnd();
4058 // The child layer should have scrolled down in its local coordinates an
4059 // amount proportional to the angle between it and the input scroll delta.
4060 gfx::Vector2d expected_scroll_delta(
4061 0, -gesture_scroll_delta.x() *
4062 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
4063 scoped_ptr<ScrollAndScaleSet> scroll_info =
4064 host_impl_->ProcessScrollDeltas();
4065 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4066 expected_scroll_delta));
4068 // The root scroll layer should have scrolled more, since the input scroll
4069 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4070 gfx::Vector2d expected_root_scroll_delta(
4071 gesture_scroll_delta.x() *
4072 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
4074 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4075 expected_root_scroll_delta));
4079 TEST_F(LayerTreeHostImplTest, ScrollPerspectiveTransformedLayer) {
4080 // When scrolling an element with perspective, the distance scrolled
4081 // depends on the point at which the scroll begins.
4082 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4083 int child_clip_layer_id = 6;
4084 int child_layer_id = 7;
4086 // Create a child layer that is rotated on its x axis, with perspective.
4087 scoped_ptr<LayerImpl> clip_layer =
4088 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
4089 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
4090 child_layer_id, scroll_layer->bounds(), clip_layer.get());
4091 LayerImpl* child_ptr = child.get();
4092 gfx::Transform perspective_transform;
4093 perspective_transform.Translate(-50.0, -50.0);
4094 perspective_transform.ApplyPerspectiveDepth(20);
4095 perspective_transform.RotateAboutXAxis(45);
4096 perspective_transform.Translate(50.0, 50.0);
4097 clip_layer->SetTransform(perspective_transform);
4099 clip_layer->SetBounds(gfx::Size(child_ptr->bounds().width() / 2,
4100 child_ptr->bounds().height() / 2));
4101 // The transform depends on the layer's transform origin, and the child layer
4102 // is a different size than the clip, so make sure the clip layer's origin
4103 // lines up over the child.
4104 clip_layer->SetTransformOrigin(gfx::Point3F(
4105 clip_layer->bounds().width(), clip_layer->bounds().height(), 0.f));
4106 clip_layer->AddChild(child.Pass());
4107 scroll_layer->AddChild(clip_layer.Pass());
4109 gfx::Size surface_size(50, 50);
4110 host_impl_->SetViewportSize(surface_size);
4112 scoped_ptr<ScrollAndScaleSet> scroll_info;
4114 gfx::Vector2d gesture_scroll_deltas[4];
4115 gesture_scroll_deltas[0] = gfx::Vector2d(4, 10);
4116 gesture_scroll_deltas[1] = gfx::Vector2d(4, 10);
4117 gesture_scroll_deltas[2] = gfx::Vector2d(10, 0);
4118 gesture_scroll_deltas[3] = gfx::Vector2d(10, 0);
4120 gfx::Vector2d expected_scroll_deltas[4];
4121 // Perspective affects the vertical delta by a different
4122 // amount depending on the vertical position of the |viewport_point|.
4123 expected_scroll_deltas[0] = gfx::Vector2d(2, 8);
4124 expected_scroll_deltas[1] = gfx::Vector2d(1, 4);
4125 // Deltas which start with the same vertical position of the
4126 // |viewport_point| are subject to identical perspective effects.
4127 expected_scroll_deltas[2] = gfx::Vector2d(4, 0);
4128 expected_scroll_deltas[3] = gfx::Vector2d(4, 0);
4130 gfx::Point viewport_point(1, 1);
4132 // Scroll in screen coordinates with a gesture. Each scroll starts
4133 // where the previous scroll ended, but the scroll position is reset
4134 // for each scroll.
4135 for (int i = 0; i < 4; ++i) {
4136 child_ptr->SetScrollDelta(gfx::Vector2dF());
4137 DrawFrame();
4138 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4139 host_impl_->ScrollBegin(viewport_point, InputHandler::GESTURE));
4140 host_impl_->ScrollBy(viewport_point, gesture_scroll_deltas[i]);
4141 viewport_point += gesture_scroll_deltas[i];
4142 host_impl_->ScrollEnd();
4144 scroll_info = host_impl_->ProcessScrollDeltas();
4145 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4146 expected_scroll_deltas[i]));
4148 // The root scroll layer should not have scrolled, because the input delta
4149 // was close to the layer's axis of movement.
4150 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4154 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
4155 LayerImpl* scroll_layer =
4156 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4158 // Scale the layer to twice its normal size.
4159 int scale = 2;
4160 gfx::Transform scale_transform;
4161 scale_transform.Scale(scale, scale);
4162 scroll_layer->SetTransform(scale_transform);
4164 gfx::Size surface_size(50, 50);
4165 host_impl_->SetViewportSize(surface_size);
4166 DrawFrame();
4168 // Scroll down in screen coordinates with a gesture.
4169 gfx::Vector2d scroll_delta(0, 10);
4170 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4171 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4172 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4173 host_impl_->ScrollEnd();
4175 // The layer should have scrolled down in its local coordinates, but half the
4176 // amount.
4177 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
4178 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4179 gfx::Vector2d(0, scroll_delta.y() / scale)));
4181 // Reset and scroll down with the wheel.
4182 scroll_layer->SetScrollDelta(gfx::Vector2dF());
4183 gfx::Vector2d wheel_scroll_delta(0, 10);
4184 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4185 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4186 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
4187 host_impl_->ScrollEnd();
4189 // It should apply the scale factor to the scroll delta for the wheel event.
4190 scroll_info = host_impl_->ProcessScrollDeltas();
4191 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4192 wheel_scroll_delta));
4195 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
4196 int width = 332;
4197 int height = 20;
4198 int scale = 3;
4199 SetupScrollAndContentsLayers(gfx::Size(width, height));
4200 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
4201 gfx::Size(width * scale - 1, height * scale));
4202 host_impl_->SetDeviceScaleFactor(scale);
4203 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4205 LayerImpl* inner_viewport_scroll_layer =
4206 host_impl_->active_tree()->InnerViewportScrollLayer();
4207 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4208 inner_viewport_scroll_layer->MaxScrollOffset());
4211 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
4212 public:
4213 TestScrollOffsetDelegate()
4214 : page_scale_factor_(0.f),
4215 min_page_scale_factor_(-1.f),
4216 max_page_scale_factor_(-1.f),
4217 needs_animate_(false) {}
4219 ~TestScrollOffsetDelegate() override {}
4221 gfx::ScrollOffset GetTotalScrollOffset() override {
4222 return getter_return_value_;
4225 bool IsExternalScrollActive() const override { return false; }
4227 void SetNeedsAnimate(const AnimationCallback&) override {
4228 needs_animate_ = true;
4231 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
4232 const gfx::ScrollOffset& max_scroll_offset,
4233 const gfx::SizeF& scrollable_size,
4234 float page_scale_factor,
4235 float min_page_scale_factor,
4236 float max_page_scale_factor) override {
4237 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
4238 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
4239 last_set_scroll_offset_ = total_scroll_offset;
4240 max_scroll_offset_ = max_scroll_offset;
4241 scrollable_size_ = scrollable_size;
4242 page_scale_factor_ = page_scale_factor;
4243 min_page_scale_factor_ = min_page_scale_factor;
4244 max_page_scale_factor_ = max_page_scale_factor;
4246 set_getter_return_value(last_set_scroll_offset_);
4249 bool GetAndResetNeedsAnimate() {
4250 bool needs_animate = needs_animate_;
4251 needs_animate_ = false;
4252 return needs_animate;
4255 gfx::ScrollOffset last_set_scroll_offset() {
4256 return last_set_scroll_offset_;
4259 void set_getter_return_value(const gfx::ScrollOffset& value) {
4260 getter_return_value_ = value;
4263 gfx::ScrollOffset max_scroll_offset() const {
4264 return max_scroll_offset_;
4267 gfx::SizeF scrollable_size() const {
4268 return scrollable_size_;
4271 float page_scale_factor() const {
4272 return page_scale_factor_;
4275 float min_page_scale_factor() const {
4276 return min_page_scale_factor_;
4279 float max_page_scale_factor() const {
4280 return max_page_scale_factor_;
4283 private:
4284 gfx::ScrollOffset last_set_scroll_offset_;
4285 gfx::ScrollOffset getter_return_value_;
4286 gfx::ScrollOffset max_scroll_offset_;
4287 gfx::SizeF scrollable_size_;
4288 float page_scale_factor_;
4289 float min_page_scale_factor_;
4290 float max_page_scale_factor_;
4291 bool needs_animate_;
4294 // TODO(jdduke): Test root fling animation.
4295 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
4296 TestScrollOffsetDelegate scroll_delegate;
4297 host_impl_->SetViewportSize(gfx::Size(10, 20));
4298 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4299 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4300 clip_layer->SetBounds(gfx::Size(10, 20));
4302 // Setting the delegate results in the current scroll offset being set.
4303 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
4304 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4305 scroll_layer->SetScrollDelta(initial_scroll_delta);
4306 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4307 EXPECT_EQ(initial_scroll_delta.ToString(),
4308 scroll_delegate.last_set_scroll_offset().ToString());
4310 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4311 // page_scale_factor and {min|max}_page_scale_factor being set.
4312 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
4313 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
4314 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4315 EXPECT_EQ(0.f, scroll_delegate.min_page_scale_factor());
4316 EXPECT_EQ(0.f, scroll_delegate.max_page_scale_factor());
4318 // Updating page scale immediately updates the delegate.
4319 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
4320 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
4321 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4322 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4323 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
4324 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
4325 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4326 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4327 host_impl_->SetPageScaleOnActiveTree(2.f);
4328 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4329 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4330 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4331 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4333 // The pinch gesture doesn't put the delegate into a state where the scroll
4334 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4335 // delegate).
4336 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
4337 host_impl_->PinchGestureBegin();
4338 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
4339 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
4340 host_impl_->PinchGestureEnd();
4341 host_impl_->ScrollEnd();
4343 // Scrolling should be relative to the offset as returned by the delegate.
4344 gfx::Vector2dF scroll_delta(0.f, 10.f);
4345 gfx::ScrollOffset current_offset(7.f, 8.f);
4347 scroll_delegate.set_getter_return_value(current_offset);
4348 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4349 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4350 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4352 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4353 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
4354 scroll_delegate.last_set_scroll_offset());
4356 current_offset = gfx::ScrollOffset(42.f, 41.f);
4357 scroll_delegate.set_getter_return_value(current_offset);
4358 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4359 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4360 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
4361 scroll_delegate.last_set_scroll_offset());
4362 host_impl_->ScrollEnd();
4363 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
4364 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4366 // Forces a full tree synchronization and ensures that the scroll delegate
4367 // sees the correct size of the new tree.
4368 gfx::Size new_size(42, 24);
4369 host_impl_->CreatePendingTree();
4370 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
4371 host_impl_->ActivateSyncTree();
4372 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
4374 // Un-setting the delegate should propagate the delegate's current offset to
4375 // the root scrollable layer.
4376 current_offset = gfx::ScrollOffset(13.f, 12.f);
4377 scroll_delegate.set_getter_return_value(current_offset);
4378 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4379 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4381 EXPECT_EQ(current_offset.ToString(),
4382 scroll_layer->CurrentScrollOffset().ToString());
4385 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
4386 const gfx::Transform target_space_transform =
4387 layer->draw_properties().target_space_transform;
4388 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
4389 gfx::Point translated_point;
4390 target_space_transform.TransformPoint(&translated_point);
4391 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
4392 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
4395 TEST_F(LayerTreeHostImplTest,
4396 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
4397 TestScrollOffsetDelegate scroll_delegate;
4398 host_impl_->SetViewportSize(gfx::Size(10, 20));
4399 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4400 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4401 clip_layer->SetBounds(gfx::Size(10, 20));
4402 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4404 // Draw first frame to clear any pending draws and check scroll.
4405 DrawFrame();
4406 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
4407 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
4409 // Set external scroll delta on delegate and notify LayerTreeHost.
4410 gfx::ScrollOffset scroll_offset(10.f, 10.f);
4411 scroll_delegate.set_getter_return_value(scroll_offset);
4412 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4414 // Check scroll delta reflected in layer.
4415 LayerTreeHostImpl::FrameData frame;
4416 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4417 host_impl_->DrawLayers(&frame);
4418 host_impl_->DidDrawAllLayers(frame);
4419 EXPECT_FALSE(frame.has_no_damage);
4420 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
4422 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4425 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
4426 InputHandlerScrollResult scroll_result;
4427 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4428 host_impl_->SetViewportSize(gfx::Size(50, 50));
4429 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4430 DrawFrame();
4431 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4433 // In-bounds scrolling does not affect overscroll.
4434 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4435 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4436 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4437 EXPECT_TRUE(scroll_result.did_scroll);
4438 EXPECT_FALSE(scroll_result.did_overscroll_root);
4439 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4440 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4442 // Overscroll events are reflected immediately.
4443 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4444 EXPECT_TRUE(scroll_result.did_scroll);
4445 EXPECT_TRUE(scroll_result.did_overscroll_root);
4446 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4447 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4448 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4449 host_impl_->accumulated_root_overscroll());
4451 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4452 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4453 EXPECT_TRUE(scroll_result.did_scroll);
4454 EXPECT_FALSE(scroll_result.did_overscroll_root);
4455 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4456 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4457 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4458 host_impl_->accumulated_root_overscroll());
4460 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4461 EXPECT_FALSE(scroll_result.did_scroll);
4462 EXPECT_TRUE(scroll_result.did_overscroll_root);
4463 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4464 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4465 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4466 host_impl_->accumulated_root_overscroll());
4468 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4469 EXPECT_TRUE(scroll_result.did_scroll);
4470 EXPECT_FALSE(scroll_result.did_overscroll_root);
4471 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4472 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4473 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4474 host_impl_->accumulated_root_overscroll());
4476 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4477 EXPECT_TRUE(scroll_result.did_scroll);
4478 EXPECT_TRUE(scroll_result.did_overscroll_root);
4479 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
4480 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
4481 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4482 host_impl_->accumulated_root_overscroll());
4484 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4485 EXPECT_TRUE(scroll_result.did_scroll);
4486 EXPECT_TRUE(scroll_result.did_overscroll_root);
4487 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4488 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
4489 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4490 host_impl_->accumulated_root_overscroll());
4492 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4493 EXPECT_TRUE(scroll_result.did_scroll);
4494 EXPECT_TRUE(scroll_result.did_overscroll_root);
4495 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4496 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4497 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4498 host_impl_->accumulated_root_overscroll());
4500 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4501 // as no scroll occurs.
4502 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4503 EXPECT_FALSE(scroll_result.did_scroll);
4504 EXPECT_TRUE(scroll_result.did_overscroll_root);
4505 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4506 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
4507 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4508 host_impl_->accumulated_root_overscroll());
4510 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4511 EXPECT_FALSE(scroll_result.did_scroll);
4512 EXPECT_TRUE(scroll_result.did_overscroll_root);
4513 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4514 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
4515 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4516 host_impl_->accumulated_root_overscroll());
4518 // Overscroll resets on valid scroll.
4519 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4520 EXPECT_TRUE(scroll_result.did_scroll);
4521 EXPECT_FALSE(scroll_result.did_overscroll_root);
4522 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4523 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4524 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4525 host_impl_->accumulated_root_overscroll());
4527 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4528 EXPECT_TRUE(scroll_result.did_scroll);
4529 EXPECT_TRUE(scroll_result.did_overscroll_root);
4530 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4531 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4532 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4533 host_impl_->accumulated_root_overscroll());
4535 host_impl_->ScrollEnd();
4539 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
4540 // Scroll child layers beyond their maximum scroll range and make sure root
4541 // overscroll does not accumulate.
4542 InputHandlerScrollResult scroll_result;
4543 gfx::Size surface_size(10, 10);
4544 scoped_ptr<LayerImpl> root_clip =
4545 LayerImpl::Create(host_impl_->active_tree(), 4);
4546 root_clip->SetHasRenderSurface(true);
4548 scoped_ptr<LayerImpl> root =
4549 CreateScrollableLayer(1, surface_size, root_clip.get());
4551 scoped_ptr<LayerImpl> grand_child =
4552 CreateScrollableLayer(3, surface_size, root_clip.get());
4554 scoped_ptr<LayerImpl> child =
4555 CreateScrollableLayer(2, surface_size, root_clip.get());
4556 LayerImpl* grand_child_layer = grand_child.get();
4557 child->AddChild(grand_child.Pass());
4559 LayerImpl* child_layer = child.get();
4560 root->AddChild(child.Pass());
4561 root_clip->AddChild(root.Pass());
4562 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4563 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4564 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4565 host_impl_->active_tree()->DidBecomeActive();
4566 host_impl_->SetViewportSize(surface_size);
4567 DrawFrame();
4569 gfx::Vector2d scroll_delta(0, -10);
4570 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4571 host_impl_->ScrollBegin(gfx::Point(),
4572 InputHandler::NON_BUBBLING_GESTURE));
4573 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4574 EXPECT_TRUE(scroll_result.did_scroll);
4575 EXPECT_FALSE(scroll_result.did_overscroll_root);
4576 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4577 host_impl_->ScrollEnd();
4579 // The next time we scroll we should only scroll the parent, but overscroll
4580 // should still not reach the root layer.
4581 scroll_delta = gfx::Vector2d(0, -30);
4582 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4583 host_impl_->ScrollBegin(gfx::Point(5, 5),
4584 InputHandler::NON_BUBBLING_GESTURE));
4585 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4586 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4587 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4588 EXPECT_TRUE(scroll_result.did_scroll);
4589 EXPECT_FALSE(scroll_result.did_overscroll_root);
4590 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
4591 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4592 host_impl_->ScrollEnd();
4594 // After scrolling the parent, another scroll on the opposite direction
4595 // should scroll the child.
4596 scroll_delta = gfx::Vector2d(0, 70);
4597 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4598 host_impl_->ScrollBegin(gfx::Point(5, 5),
4599 InputHandler::NON_BUBBLING_GESTURE));
4600 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4601 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4602 EXPECT_TRUE(scroll_result.did_scroll);
4603 EXPECT_FALSE(scroll_result.did_overscroll_root);
4604 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4605 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4606 host_impl_->ScrollEnd();
4610 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
4611 // When we try to scroll a non-scrollable child layer, the scroll delta
4612 // should be applied to one of its ancestors if possible. Overscroll should
4613 // be reflected only when it has bubbled up to the root scrolling layer.
4614 InputHandlerScrollResult scroll_result;
4615 gfx::Size surface_size(10, 10);
4616 gfx::Size content_size(20, 20);
4617 scoped_ptr<LayerImpl> root_clip =
4618 LayerImpl::Create(host_impl_->active_tree(), 3);
4619 root_clip->SetHasRenderSurface(true);
4621 scoped_ptr<LayerImpl> root =
4622 CreateScrollableLayer(1, content_size, root_clip.get());
4623 root->SetIsContainerForFixedPositionLayers(true);
4624 scoped_ptr<LayerImpl> child =
4625 CreateScrollableLayer(2, content_size, root_clip.get());
4627 child->SetScrollClipLayer(Layer::INVALID_ID);
4628 root->AddChild(child.Pass());
4629 root_clip->AddChild(root.Pass());
4631 host_impl_->SetViewportSize(surface_size);
4632 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4633 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4634 Layer::INVALID_ID);
4635 host_impl_->active_tree()->DidBecomeActive();
4636 DrawFrame();
4638 gfx::Vector2d scroll_delta(0, 8);
4639 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4640 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4641 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4642 EXPECT_TRUE(scroll_result.did_scroll);
4643 EXPECT_FALSE(scroll_result.did_overscroll_root);
4644 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4645 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4646 EXPECT_TRUE(scroll_result.did_scroll);
4647 EXPECT_TRUE(scroll_result.did_overscroll_root);
4648 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4649 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4650 EXPECT_FALSE(scroll_result.did_scroll);
4651 EXPECT_TRUE(scroll_result.did_overscroll_root);
4652 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4653 host_impl_->ScrollEnd();
4657 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4658 InputHandlerScrollResult scroll_result;
4659 LayerTreeSettings settings;
4660 CreateHostImpl(settings, CreateOutputSurface());
4662 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4663 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4664 clip_layer->SetBounds(gfx::Size(50, 50));
4665 host_impl_->SetViewportSize(gfx::Size(50, 50));
4666 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4667 DrawFrame();
4668 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4670 // Even though the layer can't scroll the overscroll still happens.
4671 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4672 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4673 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4674 EXPECT_FALSE(scroll_result.did_scroll);
4675 EXPECT_TRUE(scroll_result.did_overscroll_root);
4676 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4679 TEST_F(LayerTreeHostImplTest, NoOverscrollOnFractionalDeviceScale) {
4680 InputHandlerScrollResult scroll_result;
4681 gfx::Size surface_size(980, 1439);
4682 gfx::Size content_size(980, 1438);
4683 float device_scale_factor = 1.5f;
4684 scoped_ptr<LayerImpl> root_clip =
4685 LayerImpl::Create(host_impl_->active_tree(), 3);
4686 root_clip->SetHasRenderSurface(true);
4688 scoped_ptr<LayerImpl> root =
4689 CreateScrollableLayer(1, content_size, root_clip.get());
4690 root->SetIsContainerForFixedPositionLayers(true);
4691 scoped_ptr<LayerImpl> child =
4692 CreateScrollableLayer(2, content_size, root_clip.get());
4693 root->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4694 host_impl_->active_tree()->PushPageScaleFromMainThread(0.326531f, 0.326531f,
4695 5.f);
4696 host_impl_->SetPageScaleOnActiveTree(0.326531f);
4697 child->SetScrollClipLayer(Layer::INVALID_ID);
4698 root->AddChild(child.Pass());
4699 root_clip->AddChild(root.Pass());
4701 host_impl_->SetViewportSize(surface_size);
4702 host_impl_->SetDeviceScaleFactor(device_scale_factor);
4703 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4704 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4705 Layer::INVALID_ID);
4706 host_impl_->active_tree()->DidBecomeActive();
4707 DrawFrame();
4709 // Horizontal & Vertical GlowEffect should not be applied when
4710 // content size is less then view port size. For Example Horizontal &
4711 // vertical GlowEffect should not be applied in about:blank page.
4712 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4713 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4714 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4715 EXPECT_FALSE(scroll_result.did_scroll);
4716 EXPECT_FALSE(scroll_result.did_overscroll_root);
4717 EXPECT_EQ(gfx::Vector2dF().ToString(),
4718 host_impl_->accumulated_root_overscroll().ToString());
4720 host_impl_->ScrollEnd();
4724 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4725 InputHandlerScrollResult scroll_result;
4726 gfx::Size surface_size(100, 100);
4727 gfx::Size content_size(200, 200);
4728 scoped_ptr<LayerImpl> root_clip =
4729 LayerImpl::Create(host_impl_->active_tree(), 3);
4730 root_clip->SetHasRenderSurface(true);
4732 scoped_ptr<LayerImpl> root =
4733 CreateScrollableLayer(1, content_size, root_clip.get());
4734 root->SetIsContainerForFixedPositionLayers(true);
4735 scoped_ptr<LayerImpl> child =
4736 CreateScrollableLayer(2, content_size, root_clip.get());
4738 child->SetScrollClipLayer(Layer::INVALID_ID);
4739 root->AddChild(child.Pass());
4740 root_clip->AddChild(root.Pass());
4742 host_impl_->SetViewportSize(surface_size);
4743 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4744 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
4745 Layer::INVALID_ID);
4746 host_impl_->active_tree()->DidBecomeActive();
4747 DrawFrame();
4749 // Edge glow effect should be applicable only upon reaching Edges
4750 // of the content. unnecessary glow effect calls shouldn't be
4751 // called while scrolling up without reaching the edge of the content.
4752 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4753 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4754 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4755 EXPECT_TRUE(scroll_result.did_scroll);
4756 EXPECT_FALSE(scroll_result.did_overscroll_root);
4757 EXPECT_EQ(gfx::Vector2dF().ToString(),
4758 host_impl_->accumulated_root_overscroll().ToString());
4759 scroll_result =
4760 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4761 EXPECT_TRUE(scroll_result.did_scroll);
4762 EXPECT_FALSE(scroll_result.did_overscroll_root);
4763 EXPECT_EQ(gfx::Vector2dF().ToString(),
4764 host_impl_->accumulated_root_overscroll().ToString());
4765 host_impl_->ScrollEnd();
4766 // unusedrootDelta should be subtracted from applied delta so that
4767 // unwanted glow effect calls are not called.
4768 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4769 host_impl_->ScrollBegin(gfx::Point(0, 0),
4770 InputHandler::NON_BUBBLING_GESTURE));
4771 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
4772 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4773 EXPECT_TRUE(scroll_result.did_scroll);
4774 EXPECT_TRUE(scroll_result.did_overscroll_root);
4775 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4776 host_impl_->accumulated_root_overscroll().ToString());
4778 scroll_result =
4779 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4780 EXPECT_FALSE(scroll_result.did_scroll);
4781 EXPECT_FALSE(scroll_result.did_overscroll_root);
4782 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4783 host_impl_->accumulated_root_overscroll().ToString());
4784 host_impl_->ScrollEnd();
4785 // TestCase to check kEpsilon, which prevents minute values to trigger
4786 // gloweffect without reaching edge.
4787 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4788 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4789 scroll_result =
4790 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4791 EXPECT_FALSE(scroll_result.did_scroll);
4792 EXPECT_FALSE(scroll_result.did_overscroll_root);
4793 EXPECT_EQ(gfx::Vector2dF().ToString(),
4794 host_impl_->accumulated_root_overscroll().ToString());
4795 host_impl_->ScrollEnd();
4799 class BlendStateCheckLayer : public LayerImpl {
4800 public:
4801 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4802 int id,
4803 ResourceProvider* resource_provider) {
4804 return make_scoped_ptr(
4805 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4808 void AppendQuads(RenderPass* render_pass,
4809 AppendQuadsData* append_quads_data) override {
4810 quads_appended_ = true;
4812 gfx::Rect opaque_rect;
4813 if (contents_opaque())
4814 opaque_rect = quad_rect_;
4815 else
4816 opaque_rect = opaque_content_rect_;
4817 gfx::Rect visible_quad_rect = quad_rect_;
4819 SharedQuadState* shared_quad_state =
4820 render_pass->CreateAndAppendSharedQuadState();
4821 PopulateSharedQuadState(shared_quad_state);
4823 TileDrawQuad* test_blending_draw_quad =
4824 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4825 test_blending_draw_quad->SetNew(shared_quad_state,
4826 quad_rect_,
4827 opaque_rect,
4828 visible_quad_rect,
4829 resource_id_,
4830 gfx::RectF(0.f, 0.f, 1.f, 1.f),
4831 gfx::Size(1, 1),
4832 false,
4833 false);
4834 test_blending_draw_quad->visible_rect = quad_visible_rect_;
4835 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
4836 EXPECT_EQ(has_render_surface_, !!render_surface());
4839 void SetExpectation(bool blend, bool has_render_surface) {
4840 blend_ = blend;
4841 has_render_surface_ = has_render_surface;
4842 quads_appended_ = false;
4845 bool quads_appended() const { return quads_appended_; }
4847 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
4848 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
4849 void SetOpaqueContentRect(const gfx::Rect& rect) {
4850 opaque_content_rect_ = rect;
4853 private:
4854 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
4855 int id,
4856 ResourceProvider* resource_provider)
4857 : LayerImpl(tree_impl, id),
4858 blend_(false),
4859 has_render_surface_(false),
4860 quads_appended_(false),
4861 quad_rect_(5, 5, 5, 5),
4862 quad_visible_rect_(5, 5, 5, 5),
4863 resource_id_(resource_provider->CreateResource(
4864 gfx::Size(1, 1),
4865 GL_CLAMP_TO_EDGE,
4866 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
4867 RGBA_8888)) {
4868 resource_provider->AllocateForTesting(resource_id_);
4869 SetBounds(gfx::Size(10, 10));
4870 SetDrawsContent(true);
4873 bool blend_;
4874 bool has_render_surface_;
4875 bool quads_appended_;
4876 gfx::Rect quad_rect_;
4877 gfx::Rect opaque_content_rect_;
4878 gfx::Rect quad_visible_rect_;
4879 ResourceId resource_id_;
4882 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
4884 scoped_ptr<LayerImpl> root =
4885 LayerImpl::Create(host_impl_->active_tree(), 1);
4886 root->SetBounds(gfx::Size(10, 10));
4887 root->SetDrawsContent(false);
4888 root->SetHasRenderSurface(true);
4889 host_impl_->active_tree()->SetRootLayer(root.Pass());
4891 LayerImpl* root = host_impl_->active_tree()->root_layer();
4893 root->AddChild(
4894 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4896 host_impl_->resource_provider()));
4897 BlendStateCheckLayer* layer1 =
4898 static_cast<BlendStateCheckLayer*>(root->children()[0]);
4899 layer1->SetPosition(gfx::PointF(2.f, 2.f));
4901 LayerTreeHostImpl::FrameData frame;
4903 // Opaque layer, drawn without blending.
4904 layer1->SetContentsOpaque(true);
4905 layer1->SetExpectation(false, false);
4906 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4907 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4908 host_impl_->DrawLayers(&frame);
4909 EXPECT_TRUE(layer1->quads_appended());
4910 host_impl_->DidDrawAllLayers(frame);
4912 // Layer with translucent content and painting, so drawn with blending.
4913 layer1->SetContentsOpaque(false);
4914 layer1->SetExpectation(true, false);
4915 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4916 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4917 host_impl_->DrawLayers(&frame);
4918 EXPECT_TRUE(layer1->quads_appended());
4919 host_impl_->DidDrawAllLayers(frame);
4921 // Layer with translucent opacity, drawn with blending.
4922 layer1->SetContentsOpaque(true);
4923 layer1->SetOpacity(0.5f);
4924 layer1->SetExpectation(true, false);
4925 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4926 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4927 host_impl_->DrawLayers(&frame);
4928 EXPECT_TRUE(layer1->quads_appended());
4929 host_impl_->DidDrawAllLayers(frame);
4931 // Layer with translucent opacity and painting, drawn with blending.
4932 layer1->SetContentsOpaque(true);
4933 layer1->SetOpacity(0.5f);
4934 layer1->SetExpectation(true, false);
4935 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4936 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4937 host_impl_->DrawLayers(&frame);
4938 EXPECT_TRUE(layer1->quads_appended());
4939 host_impl_->DidDrawAllLayers(frame);
4941 layer1->AddChild(
4942 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4944 host_impl_->resource_provider()));
4945 BlendStateCheckLayer* layer2 =
4946 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
4947 layer2->SetPosition(gfx::PointF(4.f, 4.f));
4949 // 2 opaque layers, drawn without blending.
4950 layer1->SetContentsOpaque(true);
4951 layer1->SetOpacity(1.f);
4952 layer1->SetExpectation(false, false);
4953 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4954 layer2->SetContentsOpaque(true);
4955 layer2->SetOpacity(1.f);
4956 layer2->SetExpectation(false, false);
4957 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4958 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4959 host_impl_->DrawLayers(&frame);
4960 EXPECT_TRUE(layer1->quads_appended());
4961 EXPECT_TRUE(layer2->quads_appended());
4962 host_impl_->DidDrawAllLayers(frame);
4964 // Parent layer with translucent content, drawn with blending.
4965 // Child layer with opaque content, drawn without blending.
4966 layer1->SetContentsOpaque(false);
4967 layer1->SetExpectation(true, false);
4968 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4969 layer2->SetExpectation(false, false);
4970 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4971 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4972 host_impl_->DrawLayers(&frame);
4973 EXPECT_TRUE(layer1->quads_appended());
4974 EXPECT_TRUE(layer2->quads_appended());
4975 host_impl_->DidDrawAllLayers(frame);
4977 // Parent layer with translucent content but opaque painting, drawn without
4978 // blending.
4979 // Child layer with opaque content, drawn without blending.
4980 layer1->SetContentsOpaque(true);
4981 layer1->SetExpectation(false, false);
4982 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4983 layer2->SetExpectation(false, false);
4984 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4985 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4986 host_impl_->DrawLayers(&frame);
4987 EXPECT_TRUE(layer1->quads_appended());
4988 EXPECT_TRUE(layer2->quads_appended());
4989 host_impl_->DidDrawAllLayers(frame);
4991 // Parent layer with translucent opacity and opaque content. Since it has a
4992 // drawing child, it's drawn to a render surface which carries the opacity,
4993 // so it's itself drawn without blending.
4994 // Child layer with opaque content, drawn without blending (parent surface
4995 // carries the inherited opacity).
4996 layer1->SetContentsOpaque(true);
4997 layer1->SetOpacity(0.5f);
4998 layer1->SetHasRenderSurface(true);
4999 layer1->SetExpectation(false, true);
5000 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5001 layer2->SetExpectation(false, false);
5002 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5003 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5004 host_impl_->active_tree()->root_layer());
5005 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5006 host_impl_->DrawLayers(&frame);
5007 EXPECT_TRUE(layer1->quads_appended());
5008 EXPECT_TRUE(layer2->quads_appended());
5009 host_impl_->DidDrawAllLayers(frame);
5010 layer1->SetHasRenderSurface(false);
5012 // Draw again, but with child non-opaque, to make sure
5013 // layer1 not culled.
5014 layer1->SetContentsOpaque(true);
5015 layer1->SetOpacity(1.f);
5016 layer1->SetExpectation(false, false);
5017 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5018 layer2->SetContentsOpaque(true);
5019 layer2->SetOpacity(0.5f);
5020 layer2->SetExpectation(true, false);
5021 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5022 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5023 host_impl_->DrawLayers(&frame);
5024 EXPECT_TRUE(layer1->quads_appended());
5025 EXPECT_TRUE(layer2->quads_appended());
5026 host_impl_->DidDrawAllLayers(frame);
5028 // A second way of making the child non-opaque.
5029 layer1->SetContentsOpaque(true);
5030 layer1->SetOpacity(1.f);
5031 layer1->SetExpectation(false, false);
5032 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5033 layer2->SetContentsOpaque(false);
5034 layer2->SetOpacity(1.f);
5035 layer2->SetExpectation(true, false);
5036 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5037 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5038 host_impl_->DrawLayers(&frame);
5039 EXPECT_TRUE(layer1->quads_appended());
5040 EXPECT_TRUE(layer2->quads_appended());
5041 host_impl_->DidDrawAllLayers(frame);
5043 // And when the layer says its not opaque but is painted opaque, it is not
5044 // blended.
5045 layer1->SetContentsOpaque(true);
5046 layer1->SetOpacity(1.f);
5047 layer1->SetExpectation(false, false);
5048 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5049 layer2->SetContentsOpaque(true);
5050 layer2->SetOpacity(1.f);
5051 layer2->SetExpectation(false, false);
5052 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
5053 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5054 host_impl_->DrawLayers(&frame);
5055 EXPECT_TRUE(layer1->quads_appended());
5056 EXPECT_TRUE(layer2->quads_appended());
5057 host_impl_->DidDrawAllLayers(frame);
5059 // Layer with partially opaque contents, drawn with blending.
5060 layer1->SetContentsOpaque(false);
5061 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5062 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5063 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5064 layer1->SetExpectation(true, false);
5065 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5066 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5067 host_impl_->DrawLayers(&frame);
5068 EXPECT_TRUE(layer1->quads_appended());
5069 host_impl_->DidDrawAllLayers(frame);
5071 // Layer with partially opaque contents partially culled, drawn with blending.
5072 layer1->SetContentsOpaque(false);
5073 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5074 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5075 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5076 layer1->SetExpectation(true, false);
5077 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5078 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5079 host_impl_->DrawLayers(&frame);
5080 EXPECT_TRUE(layer1->quads_appended());
5081 host_impl_->DidDrawAllLayers(frame);
5083 // Layer with partially opaque contents culled, drawn with blending.
5084 layer1->SetContentsOpaque(false);
5085 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5086 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5087 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5088 layer1->SetExpectation(true, false);
5089 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5090 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5091 host_impl_->DrawLayers(&frame);
5092 EXPECT_TRUE(layer1->quads_appended());
5093 host_impl_->DidDrawAllLayers(frame);
5095 // Layer with partially opaque contents and translucent contents culled, drawn
5096 // without blending.
5097 layer1->SetContentsOpaque(false);
5098 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5099 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5100 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5101 layer1->SetExpectation(false, false);
5102 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5103 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5104 host_impl_->DrawLayers(&frame);
5105 EXPECT_TRUE(layer1->quads_appended());
5106 host_impl_->DidDrawAllLayers(frame);
5109 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
5110 protected:
5111 LayerTreeHostImplViewportCoveredTest() :
5112 gutter_quad_material_(DrawQuad::SOLID_COLOR),
5113 child_(NULL),
5114 did_activate_pending_tree_(false) {}
5116 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
5117 if (always_draw) {
5118 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5120 return FakeOutputSurface::Create3d();
5123 void SetupActiveTreeLayers() {
5124 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
5125 host_impl_->active_tree()->SetRootLayer(
5126 LayerImpl::Create(host_impl_->active_tree(), 1));
5127 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
5128 host_impl_->active_tree()->root_layer()->AddChild(
5129 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5131 host_impl_->resource_provider()));
5132 child_ = static_cast<BlendStateCheckLayer*>(
5133 host_impl_->active_tree()->root_layer()->children()[0]);
5134 child_->SetExpectation(false, false);
5135 child_->SetContentsOpaque(true);
5138 // Expect no gutter rects.
5139 void TestLayerCoversFullViewport() {
5140 gfx::Rect layer_rect(viewport_size_);
5141 child_->SetPosition(layer_rect.origin());
5142 child_->SetBounds(layer_rect.size());
5143 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5144 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5146 LayerTreeHostImpl::FrameData frame;
5147 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5148 ASSERT_EQ(1u, frame.render_passes.size());
5150 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5151 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5152 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5154 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5155 host_impl_->DidDrawAllLayers(frame);
5158 // Expect fullscreen gutter rect.
5159 void TestEmptyLayer() {
5160 gfx::Rect layer_rect(0, 0, 0, 0);
5161 child_->SetPosition(layer_rect.origin());
5162 child_->SetBounds(layer_rect.size());
5163 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5164 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5166 LayerTreeHostImpl::FrameData frame;
5167 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5168 ASSERT_EQ(1u, frame.render_passes.size());
5170 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
5171 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5172 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5174 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5175 host_impl_->DidDrawAllLayers(frame);
5178 // Expect four surrounding gutter rects.
5179 void TestLayerInMiddleOfViewport() {
5180 gfx::Rect layer_rect(500, 500, 200, 200);
5181 child_->SetPosition(layer_rect.origin());
5182 child_->SetBounds(layer_rect.size());
5183 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5184 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5186 LayerTreeHostImpl::FrameData frame;
5187 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5188 ASSERT_EQ(1u, frame.render_passes.size());
5190 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
5191 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
5192 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5194 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5195 host_impl_->DidDrawAllLayers(frame);
5198 // Expect no gutter rects.
5199 void TestLayerIsLargerThanViewport() {
5200 gfx::Rect layer_rect(viewport_size_.width() + 10,
5201 viewport_size_.height() + 10);
5202 child_->SetPosition(layer_rect.origin());
5203 child_->SetBounds(layer_rect.size());
5204 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5205 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5207 LayerTreeHostImpl::FrameData frame;
5208 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5209 ASSERT_EQ(1u, frame.render_passes.size());
5211 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5212 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5213 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5215 host_impl_->DidDrawAllLayers(frame);
5218 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
5220 void set_gutter_quad_material(DrawQuad::Material material) {
5221 gutter_quad_material_ = material;
5223 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
5224 gutter_texture_size_ = gutter_texture_size;
5227 protected:
5228 size_t CountGutterQuads(const QuadList& quad_list) {
5229 size_t num_gutter_quads = 0;
5230 for (const auto& quad : quad_list) {
5231 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
5233 return num_gutter_quads;
5236 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
5237 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5238 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
5241 // Make sure that the texture coordinates match their expectations.
5242 void ValidateTextureDrawQuads(const QuadList& quad_list) {
5243 for (const auto& quad : quad_list) {
5244 if (quad->material != DrawQuad::TEXTURE_CONTENT)
5245 continue;
5246 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
5247 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
5248 gutter_texture_size_, host_impl_->device_scale_factor());
5249 EXPECT_EQ(texture_quad->uv_top_left.x(),
5250 texture_quad->rect.x() / gutter_texture_size_pixels.width());
5251 EXPECT_EQ(texture_quad->uv_top_left.y(),
5252 texture_quad->rect.y() / gutter_texture_size_pixels.height());
5253 EXPECT_EQ(
5254 texture_quad->uv_bottom_right.x(),
5255 texture_quad->rect.right() / gutter_texture_size_pixels.width());
5256 EXPECT_EQ(
5257 texture_quad->uv_bottom_right.y(),
5258 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
5262 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
5263 return gfx::ToRoundedSize(
5264 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
5267 DrawQuad::Material gutter_quad_material_;
5268 gfx::Size gutter_texture_size_;
5269 gfx::Size viewport_size_;
5270 BlendStateCheckLayer* child_;
5271 bool did_activate_pending_tree_;
5274 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
5275 viewport_size_ = gfx::Size(1000, 1000);
5277 bool always_draw = false;
5278 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5280 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5281 SetupActiveTreeLayers();
5282 TestLayerCoversFullViewport();
5283 TestEmptyLayer();
5284 TestLayerInMiddleOfViewport();
5285 TestLayerIsLargerThanViewport();
5288 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
5289 viewport_size_ = gfx::Size(1000, 1000);
5291 bool always_draw = false;
5292 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5294 host_impl_->SetDeviceScaleFactor(2.f);
5295 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5296 SetupActiveTreeLayers();
5297 TestLayerCoversFullViewport();
5298 TestEmptyLayer();
5299 TestLayerInMiddleOfViewport();
5300 TestLayerIsLargerThanViewport();
5303 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
5304 viewport_size_ = gfx::Size(1000, 1000);
5306 bool always_draw = true;
5307 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5309 // Pending tree to force active_tree size invalid. Not used otherwise.
5310 host_impl_->CreatePendingTree();
5311 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5312 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5314 SetupActiveTreeLayers();
5315 TestEmptyLayer();
5316 TestLayerInMiddleOfViewport();
5317 TestLayerIsLargerThanViewport();
5320 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
5321 viewport_size_ = gfx::Size(1000, 1000);
5323 bool always_draw = true;
5324 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5326 // Set larger viewport and activate it to active tree.
5327 host_impl_->CreatePendingTree();
5328 gfx::Size larger_viewport(viewport_size_.width() + 100,
5329 viewport_size_.height() + 100);
5330 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
5331 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5332 host_impl_->ActivateSyncTree();
5333 EXPECT_TRUE(did_activate_pending_tree_);
5334 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
5336 // Shrink pending tree viewport without activating.
5337 host_impl_->CreatePendingTree();
5338 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5339 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5341 SetupActiveTreeLayers();
5342 TestEmptyLayer();
5343 TestLayerInMiddleOfViewport();
5344 TestLayerIsLargerThanViewport();
5347 class FakeDrawableLayerImpl: public LayerImpl {
5348 public:
5349 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5350 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
5352 protected:
5353 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
5354 : LayerImpl(tree_impl, id) {}
5357 // Only reshape when we know we are going to draw. Otherwise, the reshape
5358 // can leave the window at the wrong size if we never draw and the proper
5359 // viewport size is never set.
5360 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
5361 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5362 scoped_ptr<OutputSurface> output_surface(
5363 FakeOutputSurface::Create3d(provider));
5364 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5366 scoped_ptr<LayerImpl> root =
5367 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5368 root->SetBounds(gfx::Size(10, 10));
5369 root->SetDrawsContent(true);
5370 root->SetHasRenderSurface(true);
5371 host_impl_->active_tree()->SetRootLayer(root.Pass());
5372 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
5373 provider->TestContext3d()->clear_reshape_called();
5375 LayerTreeHostImpl::FrameData frame;
5376 host_impl_->SetViewportSize(gfx::Size(10, 10));
5377 host_impl_->SetDeviceScaleFactor(1.f);
5378 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5379 host_impl_->DrawLayers(&frame);
5380 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5381 EXPECT_EQ(provider->TestContext3d()->width(), 10);
5382 EXPECT_EQ(provider->TestContext3d()->height(), 10);
5383 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5384 host_impl_->DidDrawAllLayers(frame);
5385 provider->TestContext3d()->clear_reshape_called();
5387 host_impl_->SetViewportSize(gfx::Size(20, 30));
5388 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5389 host_impl_->DrawLayers(&frame);
5390 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5391 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5392 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5393 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5394 host_impl_->DidDrawAllLayers(frame);
5395 provider->TestContext3d()->clear_reshape_called();
5397 host_impl_->SetDeviceScaleFactor(2.f);
5398 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5399 host_impl_->DrawLayers(&frame);
5400 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5401 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5402 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5403 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
5404 host_impl_->DidDrawAllLayers(frame);
5405 provider->TestContext3d()->clear_reshape_called();
5408 // Make sure damage tracking propagates all the way to the graphics context,
5409 // where it should request to swap only the sub-buffer that is damaged.
5410 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
5411 scoped_refptr<TestContextProvider> context_provider(
5412 TestContextProvider::Create());
5413 context_provider->BindToCurrentThread();
5414 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
5416 scoped_ptr<FakeOutputSurface> output_surface(
5417 FakeOutputSurface::Create3d(context_provider));
5418 FakeOutputSurface* fake_output_surface = output_surface.get();
5420 // This test creates its own LayerTreeHostImpl, so
5421 // that we can force partial swap enabled.
5422 LayerTreeSettings settings;
5423 settings.renderer_settings.partial_swap_enabled = true;
5424 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
5425 LayerTreeHostImpl::Create(
5426 settings, this, &proxy_, &stats_instrumentation_,
5427 &shared_bitmap_manager_, NULL, &task_graph_runner_, 0);
5428 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
5429 layer_tree_host_impl->WillBeginImplFrame(
5430 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5431 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
5433 scoped_ptr<LayerImpl> root =
5434 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
5435 root->SetHasRenderSurface(true);
5436 scoped_ptr<LayerImpl> child =
5437 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
5438 child->SetPosition(gfx::PointF(12.f, 13.f));
5439 child->SetBounds(gfx::Size(14, 15));
5440 child->SetDrawsContent(true);
5441 root->SetBounds(gfx::Size(500, 500));
5442 root->SetDrawsContent(true);
5443 root->AddChild(child.Pass());
5444 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
5446 LayerTreeHostImpl::FrameData frame;
5448 // First frame, the entire screen should get swapped.
5449 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5450 layer_tree_host_impl->DrawLayers(&frame);
5451 layer_tree_host_impl->DidDrawAllLayers(frame);
5452 layer_tree_host_impl->SwapBuffers(frame);
5453 gfx::Rect expected_swap_rect(0, 0, 500, 500);
5454 EXPECT_EQ(expected_swap_rect.ToString(),
5455 fake_output_surface->last_swap_rect().ToString());
5457 // Second frame, only the damaged area should get swapped. Damage should be
5458 // the union of old and new child rects.
5459 // expected damage rect: gfx::Rect(26, 28);
5460 // expected swap rect: vertically flipped, with origin at bottom left corner.
5461 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
5462 gfx::PointF());
5463 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5464 layer_tree_host_impl->DrawLayers(&frame);
5465 host_impl_->DidDrawAllLayers(frame);
5466 layer_tree_host_impl->SwapBuffers(frame);
5468 // Make sure that partial swap is constrained to the viewport dimensions
5469 // expected damage rect: gfx::Rect(500, 500);
5470 // expected swap rect: flipped damage rect, but also clamped to viewport
5471 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
5472 EXPECT_EQ(expected_swap_rect.ToString(),
5473 fake_output_surface->last_swap_rect().ToString());
5475 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
5476 // This will damage everything.
5477 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
5478 SK_ColorBLACK);
5479 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5480 layer_tree_host_impl->DrawLayers(&frame);
5481 host_impl_->DidDrawAllLayers(frame);
5482 layer_tree_host_impl->SwapBuffers(frame);
5484 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
5485 EXPECT_EQ(expected_swap_rect.ToString(),
5486 fake_output_surface->last_swap_rect().ToString());
5489 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
5490 scoped_ptr<LayerImpl> root =
5491 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5492 scoped_ptr<LayerImpl> child =
5493 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
5494 child->SetBounds(gfx::Size(10, 10));
5495 child->SetDrawsContent(true);
5496 root->SetBounds(gfx::Size(10, 10));
5497 root->SetDrawsContent(true);
5498 root->SetHasRenderSurface(true);
5499 root->AddChild(child.Pass());
5501 host_impl_->active_tree()->SetRootLayer(root.Pass());
5503 LayerTreeHostImpl::FrameData frame;
5505 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5506 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
5507 EXPECT_EQ(1u, frame.render_passes.size());
5508 host_impl_->DidDrawAllLayers(frame);
5511 class FakeLayerWithQuads : public LayerImpl {
5512 public:
5513 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5514 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
5517 void AppendQuads(RenderPass* render_pass,
5518 AppendQuadsData* append_quads_data) override {
5519 SharedQuadState* shared_quad_state =
5520 render_pass->CreateAndAppendSharedQuadState();
5521 PopulateSharedQuadState(shared_quad_state);
5523 SkColor gray = SkColorSetRGB(100, 100, 100);
5524 gfx::Rect quad_rect(bounds());
5525 gfx::Rect visible_quad_rect(quad_rect);
5526 SolidColorDrawQuad* my_quad =
5527 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5528 my_quad->SetNew(
5529 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
5532 private:
5533 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
5534 : LayerImpl(tree_impl, id) {}
5537 class MockContext : public TestWebGraphicsContext3D {
5538 public:
5539 MOCK_METHOD1(useProgram, void(GLuint program));
5540 MOCK_METHOD5(uniform4f, void(GLint location,
5541 GLfloat x,
5542 GLfloat y,
5543 GLfloat z,
5544 GLfloat w));
5545 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
5546 GLsizei count,
5547 GLboolean transpose,
5548 const GLfloat* value));
5549 MOCK_METHOD4(drawElements, void(GLenum mode,
5550 GLsizei count,
5551 GLenum type,
5552 GLintptr offset));
5553 MOCK_METHOD1(enable, void(GLenum cap));
5554 MOCK_METHOD1(disable, void(GLenum cap));
5555 MOCK_METHOD4(scissor, void(GLint x,
5556 GLint y,
5557 GLsizei width,
5558 GLsizei height));
5561 class MockContextHarness {
5562 private:
5563 MockContext* context_;
5565 public:
5566 explicit MockContextHarness(MockContext* context)
5567 : context_(context) {
5568 context_->set_have_post_sub_buffer(true);
5570 // Catch "uninteresting" calls
5571 EXPECT_CALL(*context_, useProgram(_))
5572 .Times(0);
5574 EXPECT_CALL(*context_, drawElements(_, _, _, _))
5575 .Times(0);
5577 // These are not asserted
5578 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
5579 .WillRepeatedly(Return());
5581 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
5582 .WillRepeatedly(Return());
5584 // Any un-sanctioned calls to enable() are OK
5585 EXPECT_CALL(*context_, enable(_))
5586 .WillRepeatedly(Return());
5588 // Any un-sanctioned calls to disable() are OK
5589 EXPECT_CALL(*context_, disable(_))
5590 .WillRepeatedly(Return());
5593 void MustDrawSolidQuad() {
5594 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5595 .WillOnce(Return())
5596 .RetiresOnSaturation();
5598 EXPECT_CALL(*context_, useProgram(_))
5599 .WillOnce(Return())
5600 .RetiresOnSaturation();
5603 void MustSetScissor(int x, int y, int width, int height) {
5604 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5605 .WillRepeatedly(Return());
5607 EXPECT_CALL(*context_, scissor(x, y, width, height))
5608 .Times(AtLeast(1))
5609 .WillRepeatedly(Return());
5612 void MustSetNoScissor() {
5613 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5614 .WillRepeatedly(Return());
5616 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5617 .Times(0);
5619 EXPECT_CALL(*context_, scissor(_, _, _, _))
5620 .Times(0);
5624 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5625 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5626 MockContext* mock_context = mock_context_owned.get();
5627 MockContextHarness harness(mock_context);
5629 // Run test case
5630 LayerTreeSettings settings = DefaultSettings();
5631 settings.renderer_settings.partial_swap_enabled = false;
5632 CreateHostImpl(settings,
5633 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5634 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5636 // Without partial swap, and no clipping, no scissor is set.
5637 harness.MustDrawSolidQuad();
5638 harness.MustSetNoScissor();
5640 LayerTreeHostImpl::FrameData frame;
5641 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5642 host_impl_->DrawLayers(&frame);
5643 host_impl_->DidDrawAllLayers(frame);
5645 Mock::VerifyAndClearExpectations(&mock_context);
5647 // Without partial swap, but a layer does clip its subtree, one scissor is
5648 // set.
5649 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5650 harness.MustDrawSolidQuad();
5651 harness.MustSetScissor(0, 0, 10, 10);
5653 LayerTreeHostImpl::FrameData frame;
5654 host_impl_->active_tree()->BuildPropertyTreesForTesting();
5655 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5656 host_impl_->DrawLayers(&frame);
5657 host_impl_->DidDrawAllLayers(frame);
5659 Mock::VerifyAndClearExpectations(&mock_context);
5662 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5663 scoped_ptr<MockContext> context_owned(new MockContext);
5664 MockContext* mock_context = context_owned.get();
5665 MockContextHarness harness(mock_context);
5667 LayerTreeSettings settings = DefaultSettings();
5668 settings.renderer_settings.partial_swap_enabled = true;
5669 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5670 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5672 // The first frame is not a partially-swapped one. No scissor should be set.
5673 harness.MustSetNoScissor();
5674 harness.MustDrawSolidQuad();
5676 LayerTreeHostImpl::FrameData frame;
5677 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5678 host_impl_->DrawLayers(&frame);
5679 host_impl_->DidDrawAllLayers(frame);
5681 Mock::VerifyAndClearExpectations(&mock_context);
5683 // Damage a portion of the frame.
5684 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5685 gfx::Rect(0, 0, 2, 3));
5687 // The second frame will be partially-swapped (the y coordinates are flipped).
5688 harness.MustSetScissor(0, 7, 2, 3);
5689 harness.MustDrawSolidQuad();
5691 LayerTreeHostImpl::FrameData frame;
5692 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5693 host_impl_->DrawLayers(&frame);
5694 host_impl_->DidDrawAllLayers(frame);
5696 Mock::VerifyAndClearExpectations(&mock_context);
5699 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5700 bool partial_swap,
5701 LayerTreeHostImplClient* client,
5702 Proxy* proxy,
5703 SharedBitmapManager* manager,
5704 TaskGraphRunner* task_graph_runner,
5705 RenderingStatsInstrumentation* stats_instrumentation) {
5706 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5707 scoped_ptr<OutputSurface> output_surface(
5708 FakeOutputSurface::Create3d(provider));
5709 provider->BindToCurrentThread();
5710 provider->TestContext3d()->set_have_post_sub_buffer(true);
5712 LayerTreeSettings settings;
5713 settings.renderer_settings.partial_swap_enabled = partial_swap;
5714 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5715 LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation,
5716 manager, nullptr, task_graph_runner, 0);
5717 my_host_impl->InitializeRenderer(output_surface.Pass());
5718 my_host_impl->WillBeginImplFrame(
5719 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5720 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5723 Layers are created as follows:
5725 +--------------------+
5726 | 1 |
5727 | +-----------+ |
5728 | | 2 | |
5729 | | +-------------------+
5730 | | | 3 |
5731 | | +-------------------+
5732 | | | |
5733 | +-----------+ |
5736 +--------------------+
5738 Layers 1, 2 have render surfaces
5740 scoped_ptr<LayerImpl> root =
5741 LayerImpl::Create(my_host_impl->active_tree(), 1);
5742 scoped_ptr<LayerImpl> child =
5743 LayerImpl::Create(my_host_impl->active_tree(), 2);
5744 scoped_ptr<LayerImpl> grand_child =
5745 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5747 gfx::Rect root_rect(0, 0, 100, 100);
5748 gfx::Rect child_rect(10, 10, 50, 50);
5749 gfx::Rect grand_child_rect(5, 5, 150, 150);
5751 root->SetHasRenderSurface(true);
5752 root->SetPosition(root_rect.origin());
5753 root->SetBounds(root_rect.size());
5754 root->draw_properties().visible_layer_rect = root_rect;
5755 root->SetDrawsContent(false);
5756 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5758 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5759 child->SetOpacity(0.5f);
5760 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5761 child->draw_properties().visible_layer_rect = child_rect;
5762 child->SetDrawsContent(false);
5763 child->SetHasRenderSurface(true);
5765 grand_child->SetPosition(grand_child_rect.origin());
5766 grand_child->SetBounds(grand_child_rect.size());
5767 grand_child->draw_properties().visible_layer_rect = grand_child_rect;
5768 grand_child->SetDrawsContent(true);
5770 child->AddChild(grand_child.Pass());
5771 root->AddChild(child.Pass());
5773 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5774 return my_host_impl.Pass();
5777 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5778 TestSharedBitmapManager shared_bitmap_manager;
5779 TestTaskGraphRunner task_graph_runner;
5780 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5781 SetupLayersForOpacity(true, this, &proxy_, &shared_bitmap_manager,
5782 &task_graph_runner, &stats_instrumentation_);
5784 LayerTreeHostImpl::FrameData frame;
5785 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5787 // Verify all quads have been computed
5788 ASSERT_EQ(2U, frame.render_passes.size());
5789 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5790 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5791 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5792 frame.render_passes[0]->quad_list.front()->material);
5793 EXPECT_EQ(DrawQuad::RENDER_PASS,
5794 frame.render_passes[1]->quad_list.front()->material);
5796 my_host_impl->DrawLayers(&frame);
5797 my_host_impl->DidDrawAllLayers(frame);
5801 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5802 TestSharedBitmapManager shared_bitmap_manager;
5803 TestTaskGraphRunner task_graph_runner;
5804 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5805 SetupLayersForOpacity(false, this, &proxy_, &shared_bitmap_manager,
5806 &task_graph_runner, &stats_instrumentation_);
5808 LayerTreeHostImpl::FrameData frame;
5809 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5811 // Verify all quads have been computed
5812 ASSERT_EQ(2U, frame.render_passes.size());
5813 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5814 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5815 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5816 frame.render_passes[0]->quad_list.front()->material);
5817 EXPECT_EQ(DrawQuad::RENDER_PASS,
5818 frame.render_passes[1]->quad_list.front()->material);
5820 my_host_impl->DrawLayers(&frame);
5821 my_host_impl->DidDrawAllLayers(frame);
5825 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
5826 scoped_ptr<TestWebGraphicsContext3D> context =
5827 TestWebGraphicsContext3D::Create();
5828 TestWebGraphicsContext3D* context3d = context.get();
5829 scoped_ptr<OutputSurface> output_surface(
5830 FakeOutputSurface::Create3d(context.Pass()));
5831 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5833 scoped_ptr<LayerImpl> root_layer =
5834 LayerImpl::Create(host_impl_->active_tree(), 1);
5835 root_layer->SetBounds(gfx::Size(10, 10));
5836 root_layer->SetHasRenderSurface(true);
5838 scoped_refptr<VideoFrame> softwareFrame =
5839 media::VideoFrame::CreateColorFrame(
5840 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5841 FakeVideoFrameProvider provider;
5842 provider.set_frame(softwareFrame);
5843 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5844 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
5845 video_layer->SetBounds(gfx::Size(10, 10));
5846 video_layer->SetDrawsContent(true);
5847 root_layer->AddChild(video_layer.Pass());
5849 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
5850 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
5851 io_surface_layer->SetBounds(gfx::Size(10, 10));
5852 io_surface_layer->SetDrawsContent(true);
5853 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5854 root_layer->AddChild(io_surface_layer.Pass());
5856 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
5858 EXPECT_EQ(0u, context3d->NumTextures());
5860 LayerTreeHostImpl::FrameData frame;
5861 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5862 host_impl_->DrawLayers(&frame);
5863 host_impl_->DidDrawAllLayers(frame);
5864 host_impl_->SwapBuffers(frame);
5866 EXPECT_GT(context3d->NumTextures(), 0u);
5868 // Kill the layer tree.
5869 host_impl_->active_tree()->SetRootLayer(
5870 LayerImpl::Create(host_impl_->active_tree(), 100));
5871 // There should be no textures left in use after.
5872 EXPECT_EQ(0u, context3d->NumTextures());
5875 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
5876 public:
5877 MOCK_METHOD1(useProgram, void(GLuint program));
5878 MOCK_METHOD4(drawElements, void(GLenum mode,
5879 GLsizei count,
5880 GLenum type,
5881 GLintptr offset));
5884 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
5885 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
5886 new MockDrawQuadsToFillScreenContext);
5887 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
5889 // Run test case
5890 LayerTreeSettings settings = DefaultSettings();
5891 settings.renderer_settings.partial_swap_enabled = false;
5892 CreateHostImpl(settings,
5893 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5894 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5895 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
5897 // Verify one quad is drawn when transparent background set is not set.
5898 host_impl_->active_tree()->set_has_transparent_background(false);
5899 EXPECT_CALL(*mock_context, useProgram(_))
5900 .Times(1);
5901 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
5902 .Times(1);
5903 LayerTreeHostImpl::FrameData frame;
5904 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5905 host_impl_->DrawLayers(&frame);
5906 host_impl_->DidDrawAllLayers(frame);
5907 Mock::VerifyAndClearExpectations(&mock_context);
5909 // Verify no quads are drawn when transparent background is set.
5910 host_impl_->active_tree()->set_has_transparent_background(true);
5911 host_impl_->SetFullRootLayerDamage();
5912 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5913 host_impl_->DrawLayers(&frame);
5914 host_impl_->DidDrawAllLayers(frame);
5915 Mock::VerifyAndClearExpectations(&mock_context);
5918 class LayerTreeHostImplTestWithDelegatingRenderer
5919 : public LayerTreeHostImplTest {
5920 protected:
5921 scoped_ptr<OutputSurface> CreateOutputSurface() override {
5922 return FakeOutputSurface::CreateDelegating3d();
5925 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
5926 bool expect_to_draw = !expected_damage.IsEmpty();
5928 LayerTreeHostImpl::FrameData frame;
5929 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5931 if (!expect_to_draw) {
5932 // With no damage, we don't draw, and no quads are created.
5933 ASSERT_EQ(0u, frame.render_passes.size());
5934 } else {
5935 ASSERT_EQ(1u, frame.render_passes.size());
5937 // Verify the damage rect for the root render pass.
5938 const RenderPass* root_render_pass = frame.render_passes.back();
5939 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
5941 // Verify the root and child layers' quads are generated and not being
5942 // culled.
5943 ASSERT_EQ(2u, root_render_pass->quad_list.size());
5945 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
5946 gfx::RectF expected_child_visible_rect(child->bounds());
5947 EXPECT_EQ(expected_child_visible_rect,
5948 root_render_pass->quad_list.front()->visible_rect);
5950 LayerImpl* root = host_impl_->active_tree()->root_layer();
5951 gfx::RectF expected_root_visible_rect(root->bounds());
5952 EXPECT_EQ(expected_root_visible_rect,
5953 root_render_pass->quad_list.ElementAt(1)->visible_rect);
5956 host_impl_->DrawLayers(&frame);
5957 host_impl_->DidDrawAllLayers(frame);
5958 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
5962 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
5963 scoped_ptr<SolidColorLayerImpl> root =
5964 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5965 root->SetPosition(gfx::PointF());
5966 root->SetBounds(gfx::Size(10, 10));
5967 root->SetDrawsContent(true);
5968 root->SetHasRenderSurface(true);
5970 // Child layer is in the bottom right corner.
5971 scoped_ptr<SolidColorLayerImpl> child =
5972 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
5973 child->SetPosition(gfx::PointF(9.f, 9.f));
5974 child->SetBounds(gfx::Size(1, 1));
5975 child->SetDrawsContent(true);
5976 root->AddChild(child.Pass());
5978 host_impl_->active_tree()->SetRootLayer(root.Pass());
5980 // Draw a frame. In the first frame, the entire viewport should be damaged.
5981 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5982 DrawFrameAndTestDamage(full_frame_damage);
5984 // The second frame has damage that doesn't touch the child layer. Its quads
5985 // should still be generated.
5986 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
5987 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
5988 DrawFrameAndTestDamage(small_damage);
5990 // The third frame should have no damage, so no quads should be generated.
5991 gfx::Rect no_damage;
5992 DrawFrameAndTestDamage(no_damage);
5995 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5996 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5997 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
5998 LayerTreeSettings settings;
5999 CreateHostImpl(settings, CreateOutputSurface());
6000 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
6003 class FakeMaskLayerImpl : public LayerImpl {
6004 public:
6005 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
6006 int id) {
6007 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
6010 void GetContentsResourceId(ResourceId* resource_id,
6011 gfx::Size* resource_size) const override {
6012 *resource_id = 0;
6015 private:
6016 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
6017 : LayerImpl(tree_impl, id) {}
6020 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
6021 public:
6022 using GLRenderer::ShouldAntialiasQuad;
6025 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
6026 // Due to precision issues (especially on Android), sometimes far
6027 // away quads can end up thinking they need AA.
6028 float device_scale_factor = 4.f / 3.f;
6029 host_impl_->SetDeviceScaleFactor(device_scale_factor);
6030 gfx::Size root_size(2000, 1000);
6031 gfx::Size device_viewport_size =
6032 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
6033 host_impl_->SetViewportSize(device_viewport_size);
6035 host_impl_->CreatePendingTree();
6036 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
6037 16.f);
6039 scoped_ptr<LayerImpl> scoped_root =
6040 LayerImpl::Create(host_impl_->pending_tree(), 1);
6041 LayerImpl* root = scoped_root.get();
6042 root->SetHasRenderSurface(true);
6044 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
6046 scoped_ptr<LayerImpl> scoped_scrolling_layer =
6047 LayerImpl::Create(host_impl_->pending_tree(), 2);
6048 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
6049 root->AddChild(scoped_scrolling_layer.Pass());
6051 gfx::Size content_layer_bounds(100000, 100);
6052 gfx::Size pile_tile_size(3000, 3000);
6053 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
6054 pile_tile_size, content_layer_bounds));
6056 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
6057 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
6058 3, pile);
6059 LayerImpl* content_layer = scoped_content_layer.get();
6060 scrolling_layer->AddChild(scoped_content_layer.Pass());
6061 content_layer->SetBounds(content_layer_bounds);
6062 content_layer->SetDrawsContent(true);
6064 root->SetBounds(root_size);
6066 gfx::ScrollOffset scroll_offset(100000, 0);
6067 scrolling_layer->SetScrollClipLayer(root->id());
6068 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
6070 host_impl_->ActivateSyncTree();
6072 bool update_lcd_text = false;
6073 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
6074 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
6076 LayerTreeHostImpl::FrameData frame;
6077 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6079 ASSERT_EQ(1u, frame.render_passes.size());
6080 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
6081 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
6083 bool clipped = false, force_aa = false;
6084 gfx::QuadF device_layer_quad = MathUtil::MapQuad(
6085 quad->shared_quad_state->quad_to_target_transform,
6086 gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped);
6087 EXPECT_FALSE(clipped);
6088 bool antialiased =
6089 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6090 device_layer_quad, clipped, force_aa);
6091 EXPECT_FALSE(antialiased);
6093 host_impl_->DrawLayers(&frame);
6094 host_impl_->DidDrawAllLayers(frame);
6098 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
6099 public:
6100 CompositorFrameMetadataTest()
6101 : swap_buffers_complete_(0) {}
6103 void DidSwapBuffersCompleteOnImplThread() override {
6104 swap_buffers_complete_++;
6107 int swap_buffers_complete_;
6110 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
6111 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
6113 LayerTreeHostImpl::FrameData frame;
6114 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6115 host_impl_->DrawLayers(&frame);
6116 host_impl_->DidDrawAllLayers(frame);
6118 CompositorFrameAck ack;
6119 host_impl_->ReclaimResources(&ack);
6120 host_impl_->DidSwapBuffersComplete();
6121 EXPECT_EQ(swap_buffers_complete_, 1);
6124 class CountingSoftwareDevice : public SoftwareOutputDevice {
6125 public:
6126 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6128 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
6129 ++frames_began_;
6130 return SoftwareOutputDevice::BeginPaint(damage_rect);
6132 void EndPaint(SoftwareFrameData* frame_data) override {
6133 ++frames_ended_;
6134 SoftwareOutputDevice::EndPaint(frame_data);
6137 int frames_began_, frames_ended_;
6140 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
6141 // No main thread evictions in resourceless software mode.
6142 set_reduce_memory_result(false);
6143 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
6144 EXPECT_TRUE(CreateHostImpl(
6145 DefaultSettings(),
6146 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device))));
6147 host_impl_->SetViewportSize(gfx::Size(50, 50));
6149 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6151 const gfx::Transform external_transform;
6152 const gfx::Rect external_viewport;
6153 const gfx::Rect external_clip;
6154 const bool resourceless_software_draw = true;
6155 host_impl_->SetExternalDrawConstraints(external_transform,
6156 external_viewport,
6157 external_clip,
6158 external_viewport,
6159 external_transform,
6160 resourceless_software_draw);
6162 EXPECT_EQ(0, software_device->frames_began_);
6163 EXPECT_EQ(0, software_device->frames_ended_);
6165 DrawFrame();
6167 EXPECT_EQ(1, software_device->frames_began_);
6168 EXPECT_EQ(1, software_device->frames_ended_);
6170 // Call another API method that is likely to hit nullptr in this mode.
6171 scoped_refptr<base::trace_event::TracedValue> state =
6172 make_scoped_refptr(new base::trace_event::TracedValue());
6173 host_impl_->ActivationStateAsValueInto(state.get());
6176 TEST_F(LayerTreeHostImplTest,
6177 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
6178 set_reduce_memory_result(false);
6179 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6180 FakeOutputSurface::CreateSoftware(
6181 make_scoped_ptr(new CountingSoftwareDevice))));
6183 const gfx::Transform external_transform;
6184 const gfx::Rect external_viewport;
6185 const gfx::Rect external_clip;
6186 const bool resourceless_software_draw = true;
6187 host_impl_->SetExternalDrawConstraints(external_transform,
6188 external_viewport,
6189 external_clip,
6190 external_viewport,
6191 external_transform,
6192 resourceless_software_draw);
6194 // SolidColorLayerImpl will be drawn.
6195 scoped_ptr<SolidColorLayerImpl> root_layer =
6196 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6198 // VideoLayerImpl will not be drawn.
6199 FakeVideoFrameProvider provider;
6200 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6201 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
6202 video_layer->SetBounds(gfx::Size(10, 10));
6203 video_layer->SetDrawsContent(true);
6204 root_layer->AddChild(video_layer.Pass());
6205 SetupRootLayerImpl(root_layer.Pass());
6207 LayerTreeHostImpl::FrameData frame;
6208 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6209 host_impl_->DrawLayers(&frame);
6210 host_impl_->DidDrawAllLayers(frame);
6212 EXPECT_EQ(1u, frame.will_draw_layers.size());
6213 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
6216 // Checks that we have a non-0 default allocation if we pass a context that
6217 // doesn't support memory management extensions.
6218 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
6219 LayerTreeSettings settings;
6220 host_impl_ = LayerTreeHostImpl::Create(
6221 settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_,
6222 &gpu_memory_buffer_manager_, &task_graph_runner_, 0);
6224 scoped_ptr<OutputSurface> output_surface(
6225 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6226 host_impl_->InitializeRenderer(output_surface.Pass());
6227 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
6230 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6231 ASSERT_TRUE(host_impl_->active_tree());
6233 // RequiresHighResToDraw is set when new output surface is used.
6234 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6236 host_impl_->ResetRequiresHighResToDraw();
6238 host_impl_->SetVisible(false);
6239 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6240 host_impl_->SetVisible(true);
6241 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6242 host_impl_->SetVisible(false);
6243 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6245 host_impl_->ResetRequiresHighResToDraw();
6247 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6248 host_impl_->SetVisible(true);
6249 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6252 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6253 ASSERT_TRUE(host_impl_->active_tree());
6254 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6256 // RequiresHighResToDraw is set when new output surface is used.
6257 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6259 host_impl_->ResetRequiresHighResToDraw();
6261 host_impl_->SetContentIsSuitableForGpuRasterization(true);
6262 host_impl_->SetHasGpuRasterizationTrigger(false);
6263 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6264 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6265 host_impl_->SetHasGpuRasterizationTrigger(true);
6266 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6267 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6268 host_impl_->SetHasGpuRasterizationTrigger(false);
6269 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6270 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6272 host_impl_->ResetRequiresHighResToDraw();
6274 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6275 host_impl_->SetHasGpuRasterizationTrigger(true);
6276 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6277 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6280 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
6281 public:
6282 void SetUp() override {
6283 fake_host_impl_ =
6284 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_,
6285 &shared_bitmap_manager_, &task_graph_runner_);
6286 host_impl_.reset(fake_host_impl_);
6287 host_impl_->InitializeRenderer(CreateOutputSurface());
6288 host_impl_->SetViewportSize(gfx::Size(10, 10));
6291 FakeLayerTreeHostImpl* fake_host_impl_;
6294 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6295 fake_host_impl_->DidModifyTilePriorities();
6296 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6297 fake_host_impl_->SetVisible(false);
6298 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6301 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6302 scoped_ptr<TestWebGraphicsContext3D> context =
6303 TestWebGraphicsContext3D::Create();
6304 TestWebGraphicsContext3D* context3d = context.get();
6305 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6306 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6308 EXPECT_EQ(0u, context3d->NumTextures());
6310 UIResourceId ui_resource_id = 1;
6311 bool is_opaque = false;
6312 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6313 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6314 EXPECT_EQ(1u, context3d->NumTextures());
6315 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6316 EXPECT_NE(0u, id1);
6318 // Multiple requests with the same id is allowed. The previous texture is
6319 // deleted.
6320 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6321 EXPECT_EQ(1u, context3d->NumTextures());
6322 ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6323 EXPECT_NE(0u, id2);
6324 EXPECT_NE(id1, id2);
6326 // Deleting invalid UIResourceId is allowed and does not change state.
6327 host_impl_->DeleteUIResource(-1);
6328 EXPECT_EQ(1u, context3d->NumTextures());
6330 // Should return zero for invalid UIResourceId. Number of textures should
6331 // not change.
6332 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6333 EXPECT_EQ(1u, context3d->NumTextures());
6335 host_impl_->DeleteUIResource(ui_resource_id);
6336 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6337 EXPECT_EQ(0u, context3d->NumTextures());
6339 // Should not change state for multiple deletion on one UIResourceId
6340 host_impl_->DeleteUIResource(ui_resource_id);
6341 EXPECT_EQ(0u, context3d->NumTextures());
6344 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6345 scoped_ptr<TestWebGraphicsContext3D> context =
6346 TestWebGraphicsContext3D::Create();
6347 TestWebGraphicsContext3D* context3d = context.get();
6348 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6350 EXPECT_EQ(0u, context3d->NumTextures());
6352 gfx::Size size(4, 4);
6353 // SkImageInfo has no support for ETC1. The |info| below contains the right
6354 // total pixel size for the bitmap but not the right height and width. The
6355 // correct width/height are passed directly to UIResourceBitmap.
6356 SkImageInfo info =
6357 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6358 skia::RefPtr<SkPixelRef> pixel_ref =
6359 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6360 pixel_ref->setImmutable();
6361 UIResourceBitmap bitmap(pixel_ref, size);
6362 UIResourceId ui_resource_id = 1;
6363 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6364 EXPECT_EQ(1u, context3d->NumTextures());
6365 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6366 EXPECT_NE(0u, id1);
6369 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6372 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6373 scoped_refptr<TestContextProvider> context_provider =
6374 TestContextProvider::Create();
6376 CreateHostImpl(DefaultSettings(),
6377 FakeOutputSurface::Create3d(context_provider));
6379 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6381 ScopedPtrVector<CopyOutputRequest> requests;
6382 requests.push_back(CopyOutputRequest::CreateRequest(
6383 base::Bind(&ShutdownReleasesContext_Callback)));
6385 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6387 LayerTreeHostImpl::FrameData frame;
6388 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6389 host_impl_->DrawLayers(&frame);
6390 host_impl_->DidDrawAllLayers(frame);
6392 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6393 // texture in a texture mailbox.
6394 EXPECT_FALSE(context_provider->HasOneRef());
6395 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6397 host_impl_ = nullptr;
6399 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6400 // released, and the texture deleted.
6401 EXPECT_TRUE(context_provider->HasOneRef());
6402 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6405 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6406 // When flinging via touch, only the child should scroll (we should not
6407 // bubble).
6408 gfx::Size surface_size(10, 10);
6409 gfx::Size content_size(20, 20);
6410 scoped_ptr<LayerImpl> root_clip =
6411 LayerImpl::Create(host_impl_->active_tree(), 3);
6412 root_clip->SetHasRenderSurface(true);
6414 scoped_ptr<LayerImpl> root =
6415 CreateScrollableLayer(1, content_size, root_clip.get());
6416 root->SetIsContainerForFixedPositionLayers(true);
6417 scoped_ptr<LayerImpl> child =
6418 CreateScrollableLayer(2, content_size, root_clip.get());
6420 root->AddChild(child.Pass());
6421 int root_id = root->id();
6422 root_clip->AddChild(root.Pass());
6424 host_impl_->SetViewportSize(surface_size);
6425 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6426 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6427 Layer::INVALID_ID);
6428 host_impl_->active_tree()->DidBecomeActive();
6429 DrawFrame();
6431 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6432 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6434 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6436 gfx::Vector2d scroll_delta(0, 100);
6437 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6438 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6440 host_impl_->ScrollEnd();
6442 scoped_ptr<ScrollAndScaleSet> scroll_info =
6443 host_impl_->ProcessScrollDeltas();
6445 // Only the child should have scrolled.
6446 ASSERT_EQ(1u, scroll_info->scrolls.size());
6447 ExpectNone(*scroll_info.get(), root_id);
6451 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6452 // Scroll a child layer beyond its maximum scroll range and make sure the
6453 // the scroll doesn't bubble up to the parent layer.
6454 gfx::Size surface_size(10, 10);
6455 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6456 root->SetHasRenderSurface(true);
6457 scoped_ptr<LayerImpl> root_scrolling =
6458 CreateScrollableLayer(2, surface_size, root.get());
6460 scoped_ptr<LayerImpl> grand_child =
6461 CreateScrollableLayer(4, surface_size, root.get());
6462 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6464 scoped_ptr<LayerImpl> child =
6465 CreateScrollableLayer(3, surface_size, root.get());
6466 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6467 child->AddChild(grand_child.Pass());
6469 root_scrolling->AddChild(child.Pass());
6470 root->AddChild(root_scrolling.Pass());
6471 host_impl_->active_tree()->SetRootLayer(root.Pass());
6472 host_impl_->active_tree()->DidBecomeActive();
6473 host_impl_->SetViewportSize(surface_size);
6474 DrawFrame();
6476 scoped_ptr<ScrollAndScaleSet> scroll_info;
6477 LayerImpl* child =
6478 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6479 LayerImpl* grand_child = child->children()[0];
6481 gfx::Vector2d scroll_delta(0, -2);
6482 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6483 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6484 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6486 // The grand child should have scrolled up to its limit.
6487 scroll_info = host_impl_->ProcessScrollDeltas();
6488 ASSERT_EQ(1u, scroll_info->scrolls.size());
6489 EXPECT_TRUE(
6490 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6491 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6493 // The child should have received the bubbled delta, but the locked
6494 // scrolling layer should remain set as the grand child.
6495 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6496 scroll_info = host_impl_->ProcessScrollDeltas();
6497 ASSERT_EQ(2u, scroll_info->scrolls.size());
6498 EXPECT_TRUE(
6499 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6500 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(), scroll_delta));
6501 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6503 // The first |ScrollBy| after the fling should re-lock the scrolling
6504 // layer to the first layer that scrolled, which is the child.
6505 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6506 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6507 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6509 // The child should have scrolled up to its limit.
6510 scroll_info = host_impl_->ProcessScrollDeltas();
6511 ASSERT_EQ(2u, scroll_info->scrolls.size());
6512 EXPECT_TRUE(
6513 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6514 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(),
6515 scroll_delta + scroll_delta));
6517 // As the locked layer is at it's limit, no further scrolling can occur.
6518 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6519 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6520 host_impl_->ScrollEnd();
6524 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6525 // When flinging via wheel, the root should eventually scroll (we should
6526 // bubble).
6527 gfx::Size surface_size(10, 10);
6528 gfx::Size content_size(20, 20);
6529 scoped_ptr<LayerImpl> root_clip =
6530 LayerImpl::Create(host_impl_->active_tree(), 3);
6531 root_clip->SetHasRenderSurface(true);
6532 scoped_ptr<LayerImpl> root_scroll =
6533 CreateScrollableLayer(1, content_size, root_clip.get());
6534 int root_scroll_id = root_scroll->id();
6535 scoped_ptr<LayerImpl> child =
6536 CreateScrollableLayer(2, content_size, root_clip.get());
6538 root_scroll->AddChild(child.Pass());
6539 root_clip->AddChild(root_scroll.Pass());
6541 host_impl_->SetViewportSize(surface_size);
6542 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6543 host_impl_->active_tree()->DidBecomeActive();
6544 DrawFrame();
6546 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6547 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6549 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6551 gfx::Vector2d scroll_delta(0, 100);
6552 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6553 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6555 host_impl_->ScrollEnd();
6557 scoped_ptr<ScrollAndScaleSet> scroll_info =
6558 host_impl_->ProcessScrollDeltas();
6560 // The root should have scrolled.
6561 ASSERT_EQ(2u, scroll_info->scrolls.size());
6562 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll_id,
6563 gfx::Vector2d(0, 10)));
6567 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6568 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6569 // we should return SCROLL_UNKNOWN.
6570 gfx::Size content_size(100, 100);
6571 SetupScrollAndContentsLayers(content_size);
6573 int scroll_layer_id = 2;
6574 LayerImpl* scroll_layer =
6575 host_impl_->active_tree()->LayerById(scroll_layer_id);
6576 scroll_layer->SetDrawsContent(true);
6578 int page_scale_layer_id = 5;
6579 LayerImpl* page_scale_layer =
6580 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6582 int occluder_layer_id = 6;
6583 scoped_ptr<LayerImpl> occluder_layer =
6584 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6585 occluder_layer->SetDrawsContent(true);
6586 occluder_layer->SetBounds(content_size);
6587 occluder_layer->SetPosition(gfx::PointF());
6589 // The parent of the occluder is *above* the scroller.
6590 page_scale_layer->AddChild(occluder_layer.Pass());
6592 DrawFrame();
6594 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6595 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6598 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6599 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6600 // is not the first scroller we encounter when walking up from the layer, we
6601 // should also return SCROLL_UNKNOWN.
6602 gfx::Size content_size(100, 100);
6603 SetupScrollAndContentsLayers(content_size);
6605 int scroll_layer_id = 2;
6606 LayerImpl* scroll_layer =
6607 host_impl_->active_tree()->LayerById(scroll_layer_id);
6608 scroll_layer->SetDrawsContent(true);
6610 int occluder_layer_id = 6;
6611 scoped_ptr<LayerImpl> occluder_layer =
6612 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6613 occluder_layer->SetDrawsContent(true);
6614 occluder_layer->SetBounds(content_size);
6615 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6617 int child_scroll_clip_layer_id = 7;
6618 scoped_ptr<LayerImpl> child_scroll_clip =
6619 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6621 int child_scroll_layer_id = 8;
6622 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6623 child_scroll_layer_id, content_size, child_scroll_clip.get());
6625 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6627 child_scroll->AddChild(occluder_layer.Pass());
6628 scroll_layer->AddChild(child_scroll.Pass());
6630 DrawFrame();
6632 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6633 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6636 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
6637 gfx::Size content_size(100, 100);
6638 SetupScrollAndContentsLayers(content_size);
6640 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6642 int scroll_layer_id = 2;
6643 LayerImpl* scroll_layer =
6644 host_impl_->active_tree()->LayerById(scroll_layer_id);
6646 int child_scroll_layer_id = 7;
6647 scoped_ptr<LayerImpl> child_scroll =
6648 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6649 child_scroll->SetDrawsContent(false);
6651 scroll_layer->AddChild(child_scroll.Pass());
6653 DrawFrame();
6655 // We should not have scrolled |child_scroll| even though we technically "hit"
6656 // it. The reason for this is that if the scrolling the scroll would not move
6657 // any layer that is a drawn RSLL member, then we can ignore the hit.
6659 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6660 // started scrolling the inner viewport.
6661 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6662 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6664 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6667 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
6668 gfx::Size content_size(100, 100);
6669 SetupScrollAndContentsLayers(content_size);
6671 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6672 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
6674 scoped_ptr<LayerImpl> invisible_scroll_layer =
6675 CreateScrollableLayer(7, content_size, root);
6676 invisible_scroll_layer->SetDrawsContent(false);
6678 scoped_ptr<LayerImpl> child_layer =
6679 LayerImpl::Create(host_impl_->active_tree(), 8);
6680 child_layer->SetDrawsContent(false);
6682 scoped_ptr<LayerImpl> grand_child_layer =
6683 LayerImpl::Create(host_impl_->active_tree(), 9);
6684 grand_child_layer->SetDrawsContent(true);
6685 grand_child_layer->SetBounds(content_size);
6686 // Move the grand child so it's not hit by our test point.
6687 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
6689 child_layer->AddChild(grand_child_layer.Pass());
6690 invisible_scroll_layer->AddChild(child_layer.Pass());
6691 root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
6693 DrawFrame();
6695 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6696 // a descendant which is a drawn RSLL member.
6697 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6698 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6700 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6703 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6704 // This test case is very similar to the one above with one key difference:
6705 // the invisible scroller has a scroll child that is indeed draw contents.
6706 // If we attempt to initiate a gesture scroll off of the visible scroll child
6707 // we should still start the scroll child.
6708 gfx::Size content_size(100, 100);
6709 SetupScrollAndContentsLayers(content_size);
6711 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6713 int scroll_layer_id = 2;
6714 LayerImpl* scroll_layer =
6715 host_impl_->active_tree()->LayerById(scroll_layer_id);
6717 int scroll_child_id = 6;
6718 scoped_ptr<LayerImpl> scroll_child =
6719 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6720 scroll_child->SetDrawsContent(true);
6721 scroll_child->SetBounds(content_size);
6722 // Move the scroll child so it's not hit by our test point.
6723 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6725 int invisible_scroll_layer_id = 7;
6726 scoped_ptr<LayerImpl> invisible_scroll =
6727 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6728 invisible_scroll->SetDrawsContent(false);
6730 int container_id = 8;
6731 scoped_ptr<LayerImpl> container =
6732 LayerImpl::Create(host_impl_->active_tree(), container_id);
6734 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6735 scroll_children->insert(scroll_child.get());
6736 invisible_scroll->SetScrollChildren(scroll_children.release());
6738 scroll_child->SetScrollParent(invisible_scroll.get());
6740 container->AddChild(invisible_scroll.Pass());
6741 container->AddChild(scroll_child.Pass());
6743 scroll_layer->AddChild(container.Pass());
6745 DrawFrame();
6747 // We should have scrolled |child_scroll| even though it is invisible.
6748 // The reason for this is that if the scrolling the scroll would move a layer
6749 // that is a drawn RSLL member, then we should accept this hit.
6750 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6751 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6753 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6756 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6757 // to CompositorFrameMetadata after SwapBuffers();
6758 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6759 scoped_ptr<SolidColorLayerImpl> root =
6760 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6761 root->SetPosition(gfx::PointF());
6762 root->SetBounds(gfx::Size(10, 10));
6763 root->SetDrawsContent(true);
6764 root->SetHasRenderSurface(true);
6766 host_impl_->active_tree()->SetRootLayer(root.Pass());
6768 FakeOutputSurface* fake_output_surface =
6769 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6771 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6772 fake_output_surface->last_sent_frame().metadata.latency_info;
6773 EXPECT_TRUE(metadata_latency_before.empty());
6775 ui::LatencyInfo latency_info;
6776 latency_info.AddLatencyNumber(
6777 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6778 scoped_ptr<SwapPromise> swap_promise(
6779 new LatencyInfoSwapPromise(latency_info));
6780 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6781 host_impl_->SetNeedsRedraw();
6783 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6784 LayerTreeHostImpl::FrameData frame;
6785 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6786 host_impl_->DrawLayers(&frame);
6787 host_impl_->DidDrawAllLayers(frame);
6788 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6790 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6791 fake_output_surface->last_sent_frame().metadata.latency_info;
6792 EXPECT_EQ(1u, metadata_latency_after.size());
6793 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6794 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6797 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6798 int root_layer_id = 1;
6799 scoped_ptr<SolidColorLayerImpl> root =
6800 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6801 root->SetPosition(gfx::PointF());
6802 root->SetBounds(gfx::Size(10, 10));
6803 root->SetDrawsContent(true);
6804 root->SetHasRenderSurface(true);
6806 host_impl_->active_tree()->SetRootLayer(root.Pass());
6808 // Ensure the default frame selection bounds are empty.
6809 FakeOutputSurface* fake_output_surface =
6810 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6811 const ViewportSelection& selection_before =
6812 fake_output_surface->last_sent_frame().metadata.selection;
6813 EXPECT_EQ(ViewportSelectionBound(), selection_before.start);
6814 EXPECT_EQ(ViewportSelectionBound(), selection_before.end);
6816 // Plumb the layer-local selection bounds.
6817 gfx::PointF selection_top(5, 0);
6818 gfx::PointF selection_bottom(5, 5);
6819 LayerSelection selection;
6820 selection.start.type = SELECTION_BOUND_CENTER;
6821 selection.start.layer_id = root_layer_id;
6822 selection.start.edge_bottom = selection_bottom;
6823 selection.start.edge_top = selection_top;
6824 selection.end = selection.start;
6825 host_impl_->active_tree()->RegisterSelection(selection);
6827 // Trigger a draw-swap sequence.
6828 host_impl_->SetNeedsRedraw();
6830 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6831 LayerTreeHostImpl::FrameData frame;
6832 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6833 host_impl_->DrawLayers(&frame);
6834 host_impl_->DidDrawAllLayers(frame);
6835 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6837 // Ensure the selection bounds have propagated to the frame metadata.
6838 const ViewportSelection& selection_after =
6839 fake_output_surface->last_sent_frame().metadata.selection;
6840 EXPECT_EQ(selection.start.type, selection_after.start.type);
6841 EXPECT_EQ(selection.end.type, selection_after.end.type);
6842 EXPECT_EQ(selection_bottom, selection_after.start.edge_bottom);
6843 EXPECT_EQ(selection_top, selection_after.start.edge_top);
6844 EXPECT_TRUE(selection_after.start.visible);
6845 EXPECT_TRUE(selection_after.start.visible);
6848 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6849 public:
6850 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6851 LayerTreeHostImpl* layer_tree_host_impl,
6852 int* set_needs_commit_count,
6853 int* set_needs_redraw_count,
6854 int* forward_to_main_count)
6855 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6856 set_needs_commit_count_(set_needs_commit_count),
6857 set_needs_redraw_count_(set_needs_redraw_count),
6858 forward_to_main_count_(forward_to_main_count) {}
6860 ~SimpleSwapPromiseMonitor() override {}
6862 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
6864 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
6866 void OnForwardScrollUpdateToMainThreadOnImpl() override {
6867 (*forward_to_main_count_)++;
6870 private:
6871 int* set_needs_commit_count_;
6872 int* set_needs_redraw_count_;
6873 int* forward_to_main_count_;
6876 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6877 int set_needs_commit_count = 0;
6878 int set_needs_redraw_count = 0;
6879 int forward_to_main_count = 0;
6882 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6883 new SimpleSwapPromiseMonitor(NULL,
6884 host_impl_.get(),
6885 &set_needs_commit_count,
6886 &set_needs_redraw_count,
6887 &forward_to_main_count));
6888 host_impl_->SetNeedsRedraw();
6889 EXPECT_EQ(0, set_needs_commit_count);
6890 EXPECT_EQ(1, set_needs_redraw_count);
6891 EXPECT_EQ(0, forward_to_main_count);
6894 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6895 // monitored.
6896 host_impl_->SetNeedsRedraw();
6897 EXPECT_EQ(0, set_needs_commit_count);
6898 EXPECT_EQ(1, set_needs_redraw_count);
6899 EXPECT_EQ(0, forward_to_main_count);
6902 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6903 new SimpleSwapPromiseMonitor(NULL,
6904 host_impl_.get(),
6905 &set_needs_commit_count,
6906 &set_needs_redraw_count,
6907 &forward_to_main_count));
6908 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6909 EXPECT_EQ(0, set_needs_commit_count);
6910 EXPECT_EQ(2, set_needs_redraw_count);
6911 EXPECT_EQ(0, forward_to_main_count);
6915 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6916 new SimpleSwapPromiseMonitor(NULL,
6917 host_impl_.get(),
6918 &set_needs_commit_count,
6919 &set_needs_redraw_count,
6920 &forward_to_main_count));
6921 // Empty damage rect won't signal the monitor.
6922 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6923 EXPECT_EQ(0, set_needs_commit_count);
6924 EXPECT_EQ(2, set_needs_redraw_count);
6925 EXPECT_EQ(0, forward_to_main_count);
6929 set_needs_commit_count = 0;
6930 set_needs_redraw_count = 0;
6931 forward_to_main_count = 0;
6932 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6933 new SimpleSwapPromiseMonitor(NULL,
6934 host_impl_.get(),
6935 &set_needs_commit_count,
6936 &set_needs_redraw_count,
6937 &forward_to_main_count));
6938 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
6940 // Scrolling normally should not trigger any forwarding.
6941 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6942 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6943 EXPECT_TRUE(
6944 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6945 host_impl_->ScrollEnd();
6947 EXPECT_EQ(0, set_needs_commit_count);
6948 EXPECT_EQ(1, set_needs_redraw_count);
6949 EXPECT_EQ(0, forward_to_main_count);
6951 // Scrolling with a scroll handler should defer the swap to the main
6952 // thread.
6953 scroll_layer->SetHaveScrollEventHandlers(true);
6954 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6955 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6956 EXPECT_TRUE(
6957 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6958 host_impl_->ScrollEnd();
6960 EXPECT_EQ(0, set_needs_commit_count);
6961 EXPECT_EQ(2, set_needs_redraw_count);
6962 EXPECT_EQ(1, forward_to_main_count);
6966 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6967 public:
6968 void SetUp() override {
6969 LayerTreeSettings settings = DefaultSettings();
6970 CreateHostImpl(settings, CreateOutputSurface());
6971 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
6972 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
6973 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
6976 protected:
6977 static const int top_controls_height_;
6980 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6982 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6983 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6984 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6985 host_impl_->Animate(base::TimeTicks());
6986 EXPECT_FALSE(did_request_redraw_);
6989 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
6990 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6991 EXPECT_FALSE(did_request_redraw_);
6992 host_impl_->CreatePendingTree();
6993 host_impl_->sync_tree()->set_top_controls_height(100);
6994 host_impl_->ActivateSyncTree();
6995 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
6998 TEST_F(LayerTreeHostImplWithTopControlsTest,
6999 TopControlsStayFullyVisibleOnHeightChange) {
7000 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7001 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7003 host_impl_->CreatePendingTree();
7004 host_impl_->sync_tree()->set_top_controls_height(0);
7005 host_impl_->ActivateSyncTree();
7006 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7008 host_impl_->CreatePendingTree();
7009 host_impl_->sync_tree()->set_top_controls_height(50);
7010 host_impl_->ActivateSyncTree();
7011 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
7014 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
7015 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7016 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7017 host_impl_->DidChangeTopControlsPosition();
7018 EXPECT_TRUE(did_request_animate_);
7019 EXPECT_TRUE(did_request_redraw_);
7022 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
7023 InputHandlerScrollResult result;
7024 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7025 host_impl_->SetViewportSize(gfx::Size(100, 100));
7026 host_impl_->top_controls_manager()->UpdateTopControlsState(
7027 BOTH, SHOWN, false);
7028 DrawFrame();
7030 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7031 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7032 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7033 EXPECT_EQ(gfx::Vector2dF().ToString(),
7034 scroll_layer->CurrentScrollOffset().ToString());
7036 // Scroll just the top controls and verify that the scroll succeeds.
7037 const float residue = 10;
7038 float offset = top_controls_height_ - residue;
7039 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7040 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7041 EXPECT_TRUE(result.did_scroll);
7042 EXPECT_FLOAT_EQ(-offset,
7043 host_impl_->top_controls_manager()->ControlsTopOffset());
7044 EXPECT_EQ(gfx::Vector2dF().ToString(),
7045 scroll_layer->CurrentScrollOffset().ToString());
7047 // Scroll across the boundary
7048 const float content_scroll = 20;
7049 offset = residue + content_scroll;
7050 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7051 EXPECT_TRUE(result.did_scroll);
7052 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7053 EXPECT_EQ(-top_controls_height_,
7054 host_impl_->top_controls_manager()->ControlsTopOffset());
7055 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
7056 scroll_layer->CurrentScrollOffset().ToString());
7058 // Now scroll back to the top of the content
7059 offset = -content_scroll;
7060 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7061 EXPECT_TRUE(result.did_scroll);
7062 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7063 EXPECT_EQ(-top_controls_height_,
7064 host_impl_->top_controls_manager()->ControlsTopOffset());
7065 EXPECT_EQ(gfx::Vector2dF().ToString(),
7066 scroll_layer->CurrentScrollOffset().ToString());
7068 // And scroll the top controls completely into view
7069 offset = -top_controls_height_;
7070 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7071 EXPECT_TRUE(result.did_scroll);
7072 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
7073 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7074 EXPECT_EQ(gfx::Vector2dF().ToString(),
7075 scroll_layer->CurrentScrollOffset().ToString());
7077 // And attempt to scroll past the end
7078 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
7079 EXPECT_FALSE(result.did_scroll);
7080 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50));
7081 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7082 EXPECT_EQ(gfx::Vector2dF().ToString(),
7083 scroll_layer->CurrentScrollOffset().ToString());
7085 host_impl_->ScrollEnd();
7088 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
7089 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7090 host_impl_->SetViewportSize(gfx::Size(100, 200));
7091 host_impl_->top_controls_manager()->UpdateTopControlsState(
7092 BOTH, SHOWN, false);
7093 DrawFrame();
7095 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7096 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7097 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7098 EXPECT_EQ(gfx::Vector2dF().ToString(),
7099 scroll_layer->CurrentScrollOffset().ToString());
7101 // Scroll the top controls partially.
7102 const float residue = 35;
7103 float offset = top_controls_height_ - residue;
7104 EXPECT_TRUE(
7105 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7106 EXPECT_FLOAT_EQ(-offset,
7107 host_impl_->top_controls_manager()->ControlsTopOffset());
7108 EXPECT_EQ(gfx::Vector2dF().ToString(),
7109 scroll_layer->CurrentScrollOffset().ToString());
7111 did_request_redraw_ = false;
7112 did_request_animate_ = false;
7113 did_request_commit_ = false;
7115 // End the scroll while the controls are still offset from their limit.
7116 host_impl_->ScrollEnd();
7117 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7118 EXPECT_TRUE(did_request_animate_);
7119 EXPECT_TRUE(did_request_redraw_);
7120 EXPECT_FALSE(did_request_commit_);
7122 // The top controls should properly animate until finished, despite the scroll
7123 // offset being at the origin.
7124 base::TimeTicks animation_time = base::TimeTicks::Now();
7125 while (did_request_animate_) {
7126 did_request_redraw_ = false;
7127 did_request_animate_ = false;
7128 did_request_commit_ = false;
7130 float old_offset =
7131 host_impl_->top_controls_manager()->ControlsTopOffset();
7133 animation_time += base::TimeDelta::FromMilliseconds(5);
7134 host_impl_->Animate(animation_time);
7135 EXPECT_EQ(gfx::Vector2dF().ToString(),
7136 scroll_layer->CurrentScrollOffset().ToString());
7138 float new_offset =
7139 host_impl_->top_controls_manager()->ControlsTopOffset();
7141 // No commit is needed as the controls are animating the content offset,
7142 // not the scroll offset.
7143 EXPECT_FALSE(did_request_commit_);
7145 if (new_offset != old_offset)
7146 EXPECT_TRUE(did_request_redraw_);
7148 if (new_offset != 0) {
7149 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
7150 EXPECT_TRUE(did_request_animate_);
7153 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7156 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
7157 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7158 host_impl_->SetViewportSize(gfx::Size(100, 100));
7159 host_impl_->top_controls_manager()->UpdateTopControlsState(
7160 BOTH, SHOWN, false);
7161 float initial_scroll_offset = 50;
7162 scroll_layer->PushScrollOffsetFromMainThread(
7163 gfx::ScrollOffset(0, initial_scroll_offset));
7164 DrawFrame();
7166 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7167 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7168 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7169 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7170 scroll_layer->CurrentScrollOffset().ToString());
7172 // Scroll the top controls partially.
7173 const float residue = 15;
7174 float offset = top_controls_height_ - residue;
7175 EXPECT_TRUE(
7176 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7177 EXPECT_FLOAT_EQ(-offset,
7178 host_impl_->top_controls_manager()->ControlsTopOffset());
7179 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7180 scroll_layer->CurrentScrollOffset().ToString());
7182 did_request_redraw_ = false;
7183 did_request_animate_ = false;
7184 did_request_commit_ = false;
7186 // End the scroll while the controls are still offset from the limit.
7187 host_impl_->ScrollEnd();
7188 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7189 EXPECT_TRUE(did_request_animate_);
7190 EXPECT_TRUE(did_request_redraw_);
7191 EXPECT_FALSE(did_request_commit_);
7193 // Animate the top controls to the limit.
7194 base::TimeTicks animation_time = base::TimeTicks::Now();
7195 while (did_request_animate_) {
7196 did_request_redraw_ = false;
7197 did_request_animate_ = false;
7198 did_request_commit_ = false;
7200 float old_offset =
7201 host_impl_->top_controls_manager()->ControlsTopOffset();
7203 animation_time += base::TimeDelta::FromMilliseconds(5);
7204 host_impl_->Animate(animation_time);
7206 float new_offset =
7207 host_impl_->top_controls_manager()->ControlsTopOffset();
7209 if (new_offset != old_offset) {
7210 EXPECT_TRUE(did_request_redraw_);
7211 EXPECT_TRUE(did_request_commit_);
7214 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7215 EXPECT_EQ(-top_controls_height_,
7216 host_impl_->top_controls_manager()->ControlsTopOffset());
7219 TEST_F(LayerTreeHostImplWithTopControlsTest,
7220 TopControlsAnimationAfterMainThreadFlingStopped) {
7221 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7222 host_impl_->SetViewportSize(gfx::Size(100, 100));
7223 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7224 false);
7225 float initial_scroll_offset = 50;
7226 scroll_layer->PushScrollOffsetFromMainThread(
7227 gfx::ScrollOffset(0, initial_scroll_offset));
7228 DrawFrame();
7230 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7231 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7232 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7233 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7234 scroll_layer->CurrentScrollOffset().ToString());
7236 // Scroll the top controls partially.
7237 const float residue = 15;
7238 float offset = top_controls_height_ - residue;
7239 EXPECT_TRUE(
7240 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7241 EXPECT_FLOAT_EQ(-offset,
7242 host_impl_->top_controls_manager()->ControlsTopOffset());
7243 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7244 scroll_layer->CurrentScrollOffset().ToString());
7246 did_request_redraw_ = false;
7247 did_request_animate_ = false;
7248 did_request_commit_ = false;
7250 // End the fling while the controls are still offset from the limit.
7251 host_impl_->MainThreadHasStoppedFlinging();
7252 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7253 EXPECT_TRUE(did_request_animate_);
7254 EXPECT_TRUE(did_request_redraw_);
7255 EXPECT_FALSE(did_request_commit_);
7257 // Animate the top controls to the limit.
7258 base::TimeTicks animation_time = base::TimeTicks::Now();
7259 while (did_request_animate_) {
7260 did_request_redraw_ = false;
7261 did_request_animate_ = false;
7262 did_request_commit_ = false;
7264 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7266 animation_time += base::TimeDelta::FromMilliseconds(5);
7267 host_impl_->Animate(animation_time);
7269 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7271 if (new_offset != old_offset) {
7272 EXPECT_TRUE(did_request_redraw_);
7273 EXPECT_TRUE(did_request_commit_);
7276 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7277 EXPECT_EQ(-top_controls_height_,
7278 host_impl_->top_controls_manager()->ControlsTopOffset());
7281 TEST_F(LayerTreeHostImplWithTopControlsTest,
7282 TopControlsScrollDeltaInOverScroll) {
7283 // Verifies that the overscroll delta should not have accumulated in
7284 // the top controls if we do a hide and show without releasing finger.
7286 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7287 host_impl_->SetViewportSize(gfx::Size(100, 100));
7288 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7289 false);
7290 DrawFrame();
7292 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7293 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7294 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7296 float offset = 50;
7297 EXPECT_TRUE(
7298 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7299 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7300 EXPECT_EQ(gfx::Vector2dF().ToString(),
7301 scroll_layer->CurrentScrollOffset().ToString());
7303 EXPECT_TRUE(
7304 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7305 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7306 scroll_layer->CurrentScrollOffset().ToString());
7308 EXPECT_TRUE(
7309 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7311 // Should have fully scrolled
7312 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7313 scroll_layer->CurrentScrollOffset().ToString());
7315 float overscrollamount = 10;
7317 // Overscroll the content
7318 EXPECT_FALSE(
7319 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7320 .did_scroll);
7321 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7322 scroll_layer->CurrentScrollOffset().ToString());
7323 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7324 host_impl_->accumulated_root_overscroll().ToString());
7326 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7327 .did_scroll);
7328 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7329 scroll_layer->CurrentScrollOffset().ToString());
7330 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7332 EXPECT_TRUE(
7333 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7334 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7335 scroll_layer->CurrentScrollOffset().ToString());
7337 // Top controls should be fully visible
7338 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7340 host_impl_->ScrollEnd();
7343 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7344 public:
7345 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7346 const gfx::Size& outer_viewport,
7347 const gfx::Size& inner_viewport) {
7348 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7349 const int kOuterViewportClipLayerId = 6;
7350 const int kOuterViewportScrollLayerId = 7;
7351 const int kInnerViewportScrollLayerId = 2;
7352 const int kInnerViewportClipLayerId = 4;
7353 const int kPageScaleLayerId = 5;
7355 scoped_ptr<LayerImpl> inner_scroll =
7356 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7357 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7358 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7360 scoped_ptr<LayerImpl> inner_clip =
7361 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7362 inner_clip->SetBounds(inner_viewport);
7364 scoped_ptr<LayerImpl> page_scale =
7365 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7367 inner_scroll->SetScrollClipLayer(inner_clip->id());
7368 inner_scroll->SetBounds(outer_viewport);
7369 inner_scroll->SetPosition(gfx::PointF());
7371 scoped_ptr<LayerImpl> outer_clip =
7372 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7373 outer_clip->SetBounds(outer_viewport);
7374 outer_clip->SetIsContainerForFixedPositionLayers(true);
7376 scoped_ptr<LayerImpl> outer_scroll =
7377 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7378 outer_scroll->SetScrollClipLayer(outer_clip->id());
7379 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7380 outer_scroll->SetBounds(content_size);
7381 outer_scroll->SetPosition(gfx::PointF());
7383 scoped_ptr<LayerImpl> contents =
7384 LayerImpl::Create(layer_tree_impl, 8);
7385 contents->SetDrawsContent(true);
7386 contents->SetBounds(content_size);
7387 contents->SetPosition(gfx::PointF());
7389 outer_scroll->AddChild(contents.Pass());
7390 outer_clip->AddChild(outer_scroll.Pass());
7391 inner_scroll->AddChild(outer_clip.Pass());
7392 page_scale->AddChild(inner_scroll.Pass());
7393 inner_clip->AddChild(page_scale.Pass());
7395 inner_clip->SetHasRenderSurface(true);
7396 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7397 layer_tree_impl->SetViewportLayersFromIds(
7398 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7399 kOuterViewportScrollLayerId);
7401 host_impl_->active_tree()->DidBecomeActive();
7405 TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
7406 gfx::Size content_size = gfx::Size(100, 160);
7407 gfx::Size outer_viewport = gfx::Size(50, 80);
7408 gfx::Size inner_viewport = gfx::Size(25, 40);
7410 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7412 TestScrollOffsetDelegate scroll_delegate;
7413 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
7415 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7416 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7417 DrawFrame();
7419 gfx::ScrollOffset inner_expected;
7420 gfx::ScrollOffset outer_expected;
7421 EXPECT_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7422 EXPECT_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7424 gfx::ScrollOffset current_offset(70.f, 100.f);
7426 scroll_delegate.set_getter_return_value(current_offset);
7427 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
7428 EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
7429 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
7431 // Outer viewport scrolls first. Then the rest is applied to the inner
7432 // viewport.
7433 EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f),
7434 inner_scroll->CurrentScrollOffset());
7435 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f),
7436 outer_scroll->CurrentScrollOffset());
7440 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7441 gfx::Size content_size = gfx::Size(100, 160);
7442 gfx::Size outer_viewport = gfx::Size(50, 80);
7443 gfx::Size inner_viewport = gfx::Size(25, 40);
7445 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7447 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7448 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7449 DrawFrame();
7451 gfx::Vector2dF inner_expected;
7452 gfx::Vector2dF outer_expected;
7453 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7454 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7456 // Make sure the fling goes to the outer viewport first
7457 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7458 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7459 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7460 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7461 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7463 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7464 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7465 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7466 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), outer_scroll);
7468 host_impl_->ScrollEnd();
7469 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7471 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7472 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7474 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7475 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7476 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7477 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7478 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7479 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7481 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7482 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7483 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7485 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7486 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7487 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7489 host_impl_->ScrollEnd();
7490 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7492 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7493 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7497 TEST_F(LayerTreeHostImplVirtualViewportTest,
7498 DiagonalScrollBubblesPerfectlyToInner) {
7499 gfx::Size content_size = gfx::Size(100, 160);
7500 gfx::Size outer_viewport = gfx::Size(50, 80);
7501 gfx::Size inner_viewport = gfx::Size(25, 40);
7503 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7505 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7506 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7507 DrawFrame();
7509 gfx::Vector2dF inner_expected;
7510 gfx::Vector2dF outer_expected;
7511 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7512 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7514 // Make sure the scroll goes to the outer viewport first.
7515 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7516 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7517 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7518 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7519 InputHandler::GESTURE));
7521 // Scroll near the edge of the outer viewport.
7522 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7523 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7524 outer_expected += scroll_delta;
7525 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7526 InputHandler::GESTURE));
7528 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7529 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7531 // Now diagonal scroll across the outer viewport boundary in a single event.
7532 // The entirety of the scroll should be consumed, as bubbling between inner
7533 // and outer viewport layers is perfect.
7534 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7535 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7536 InputHandler::GESTURE));
7537 outer_expected += scroll_delta;
7538 inner_expected += scroll_delta;
7539 host_impl_->ScrollEnd();
7540 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7541 gfx::Point(), InputHandler::GESTURE));
7543 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7544 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7548 TEST_F(LayerTreeHostImplVirtualViewportTest,
7549 TouchFlingCanLockToViewportLayerAfterBubbling) {
7550 gfx::Size content_size = gfx::Size(100, 160);
7551 gfx::Size outer_viewport = gfx::Size(50, 80);
7552 gfx::Size inner_viewport = gfx::Size(25, 40);
7554 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7556 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7557 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7559 scoped_ptr<LayerImpl> child =
7560 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7561 LayerImpl* child_scroll = child.get();
7562 outer_scroll->children()[0]->AddChild(child.Pass());
7564 DrawFrame();
7566 scoped_ptr<ScrollAndScaleSet> scroll_info;
7568 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7569 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7570 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7571 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7572 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7573 InputHandler::GESTURE));
7575 // The child should have scrolled up to its limit.
7576 scroll_info = host_impl_->ProcessScrollDeltas();
7577 ASSERT_EQ(1u, scroll_info->scrolls.size());
7578 EXPECT_TRUE(
7579 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7580 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7582 // The first |ScrollBy| after the fling should re-lock the scrolling
7583 // layer to the first layer that scrolled, the inner viewport scroll layer.
7584 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7585 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7586 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7587 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7588 InputHandler::GESTURE));
7590 // The inner viewport should have scrolled up to its limit.
7591 scroll_info = host_impl_->ProcessScrollDeltas();
7592 ASSERT_EQ(2u, scroll_info->scrolls.size());
7593 EXPECT_TRUE(
7594 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7595 EXPECT_TRUE(
7596 ScrollInfoContains(*scroll_info, inner_scroll->id(), scroll_delta));
7598 // As the locked layer is at its limit, no further scrolling can occur.
7599 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7600 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7601 host_impl_->ScrollEnd();
7602 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7603 gfx::Point(), InputHandler::GESTURE));
7607 TEST_F(LayerTreeHostImplVirtualViewportTest,
7608 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest) {
7609 gfx::Size content_size = gfx::Size(100, 160);
7610 gfx::Size outer_viewport = gfx::Size(50, 80);
7611 gfx::Size inner_viewport = gfx::Size(25, 40);
7613 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7615 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7616 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7618 scoped_ptr<LayerImpl> child =
7619 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7620 LayerImpl* child_scroll = child.get();
7621 outer_scroll->children()[0]->AddChild(child.Pass());
7623 DrawFrame();
7625 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7626 host_impl_->RootScrollBegin(InputHandler::GESTURE));
7627 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7628 host_impl_->ScrollEnd();
7629 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7630 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7631 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7632 host_impl_->ScrollEnd();
7635 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7636 public:
7637 void SetUp() override {
7638 LayerTreeSettings settings = DefaultSettings();
7639 settings.max_memory_for_prepaint_percentage = 50;
7640 CreateHostImpl(settings, CreateOutputSurface());
7644 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7645 // Set up a memory policy and percentages which could cause
7646 // 32-bit integer overflows.
7647 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7649 // Verify implicit limits are calculated correctly with no overflows
7650 host_impl_->SetMemoryPolicy(mem_policy);
7651 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7652 300u * 1024u * 1024u);
7653 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7654 150u * 1024u * 1024u);
7657 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7658 const gfx::Size layer_size(100, 100);
7659 gfx::Transform external_transform;
7660 const gfx::Rect external_viewport(layer_size);
7661 const gfx::Rect external_clip(layer_size);
7662 const bool resourceless_software_draw = false;
7663 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7665 host_impl_->SetExternalDrawConstraints(external_transform,
7666 external_viewport,
7667 external_clip,
7668 external_viewport,
7669 external_transform,
7670 resourceless_software_draw);
7671 DrawFrame();
7672 EXPECT_TRANSFORMATION_MATRIX_EQ(
7673 external_transform, layer->draw_properties().target_space_transform);
7675 external_transform.Translate(20, 20);
7676 host_impl_->SetExternalDrawConstraints(external_transform,
7677 external_viewport,
7678 external_clip,
7679 external_viewport,
7680 external_transform,
7681 resourceless_software_draw);
7682 DrawFrame();
7683 EXPECT_TRANSFORMATION_MATRIX_EQ(
7684 external_transform, layer->draw_properties().target_space_transform);
7687 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
7688 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7689 DrawFrame();
7691 base::TimeTicks start_time =
7692 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7694 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7695 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7697 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7699 host_impl_->Animate(start_time);
7700 host_impl_->UpdateAnimationState(true);
7702 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
7704 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7705 host_impl_->UpdateAnimationState(true);
7707 float y = scrolling_layer->CurrentScrollOffset().y();
7708 EXPECT_TRUE(y > 1 && y < 49);
7710 // Update target.
7711 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7712 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7714 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7715 host_impl_->UpdateAnimationState(true);
7717 y = scrolling_layer->CurrentScrollOffset().y();
7718 EXPECT_TRUE(y > 50 && y < 100);
7719 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7721 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7722 host_impl_->UpdateAnimationState(true);
7724 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7725 scrolling_layer->CurrentScrollOffset());
7726 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7729 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
7730 TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
7731 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7732 DrawFrame();
7734 base::TimeTicks start_time =
7735 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7737 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7738 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7740 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7742 host_impl_->Animate(start_time);
7743 host_impl_->UpdateAnimationState(true);
7745 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
7747 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7748 host_impl_->UpdateAnimationState(true);
7750 float y = scrolling_layer->CurrentScrollOffset().y();
7751 EXPECT_TRUE(y > 1 && y < 49);
7753 // Update target.
7754 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7755 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7757 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7758 host_impl_->UpdateAnimationState(true);
7760 y = scrolling_layer->CurrentScrollOffset().y();
7761 EXPECT_TRUE(y > 50 && y < 100);
7762 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7764 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7765 host_impl_->UpdateAnimationState(true);
7767 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7768 scrolling_layer->CurrentScrollOffset());
7769 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7772 TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) {
7773 host_impl_->CreatePendingTree();
7775 Region empty_invalidation;
7776 scoped_refptr<RasterSource> pile_with_tiles(
7777 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7778 gfx::Size(10, 10)));
7780 scoped_ptr<FakePictureLayerImpl> layer =
7781 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11);
7782 layer->SetBounds(gfx::Size(10, 10));
7783 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
7784 layer->SetDrawsContent(true);
7785 layer->tilings()->AddTiling(1.0f, pile_with_tiles);
7786 layer->UpdateRasterSource(pile_with_tiles, &empty_invalidation, nullptr);
7787 layer->tilings()->tiling_at(0)->set_resolution(
7788 TileResolution::HIGH_RESOLUTION);
7789 layer->tilings()->tiling_at(0)->CreateAllTilesForTesting();
7790 layer->tilings()->tiling_at(0)->ComputeTilePriorityRects(
7791 gfx::Rect(gfx::Size(10, 10)), 1.f, 1.0, Occlusion());
7792 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
7794 FakePictureLayerImpl* root_layer = static_cast<FakePictureLayerImpl*>(
7795 host_impl_->pending_tree()->root_layer());
7797 root_layer->set_has_valid_tile_priorities(true);
7798 scoped_ptr<RasterTilePriorityQueue> non_empty_raster_priority_queue_all =
7799 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
7800 RasterTilePriorityQueue::Type::ALL);
7801 EXPECT_FALSE(non_empty_raster_priority_queue_all->IsEmpty());
7803 root_layer->set_has_valid_tile_priorities(false);
7804 scoped_ptr<RasterTilePriorityQueue> empty_raster_priority_queue_all =
7805 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
7806 RasterTilePriorityQueue::Type::ALL);
7807 EXPECT_TRUE(empty_raster_priority_queue_all->IsEmpty());
7810 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
7811 host_impl_->CreatePendingTree();
7812 host_impl_->ActivateSyncTree();
7813 host_impl_->CreatePendingTree();
7815 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7817 scoped_ptr<FakePictureLayerImpl> pending_layer =
7818 FakePictureLayerImpl::Create(pending_tree, 10);
7819 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
7820 pending_tree->SetRootLayer(pending_layer.Pass());
7821 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
7823 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
7824 pending_tree->DidBecomeActive();
7825 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7827 scoped_ptr<FakePictureLayerImpl> mask_layer =
7828 FakePictureLayerImpl::Create(pending_tree, 11);
7829 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
7830 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
7831 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
7833 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7834 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
7835 pending_tree->DidBecomeActive();
7836 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7837 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7839 scoped_ptr<FakePictureLayerImpl> replica_layer =
7840 FakePictureLayerImpl::Create(pending_tree, 12);
7841 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
7842 FakePictureLayerImpl::Create(pending_tree, 13);
7843 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
7844 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
7845 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
7846 ASSERT_EQ(raw_replica_mask_layer,
7847 raw_pending_layer->replica_layer()->mask_layer());
7849 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7850 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7851 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
7852 pending_tree->DidBecomeActive();
7853 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
7854 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
7855 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
7858 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
7859 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7860 host_impl_->SetViewportSize(gfx::Size(50, 50));
7861 DrawFrame();
7863 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
7865 float min_page_scale = 1.f, max_page_scale = 4.f;
7866 float page_scale_factor = 1.f;
7868 // The scroll deltas should have the page scale factor applied.
7870 host_impl_->active_tree()->PushPageScaleFromMainThread(
7871 page_scale_factor, min_page_scale, max_page_scale);
7872 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
7873 scroll_layer->SetScrollDelta(gfx::Vector2d());
7875 float page_scale_delta = 2.f;
7876 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
7877 host_impl_->PinchGestureBegin();
7878 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
7879 host_impl_->PinchGestureEnd();
7880 host_impl_->ScrollEnd();
7882 gfx::Vector2dF scroll_delta(0, 5);
7883 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7884 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7885 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
7887 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7888 host_impl_->ScrollEnd();
7889 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7890 scroll_layer->CurrentScrollOffset());
7894 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
7895 public:
7896 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7897 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
7899 protected:
7900 int num_lost_surfaces_;
7903 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
7904 // Really we just need at least one client notification each time
7905 // we go from having a valid output surface to not having a valid output
7906 // surface.
7907 EXPECT_EQ(0, num_lost_surfaces_);
7908 host_impl_->DidLoseOutputSurface();
7909 EXPECT_EQ(1, num_lost_surfaces_);
7910 host_impl_->DidLoseOutputSurface();
7911 EXPECT_LE(1, num_lost_surfaces_);
7914 TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) {
7915 LayerTreeHostImpl::FrameData frame;
7916 frame.render_passes.push_back(RenderPass::Create());
7917 RenderPass* pass3 = frame.render_passes.back();
7918 frame.render_passes.push_back(RenderPass::Create());
7919 RenderPass* pass2 = frame.render_passes.back();
7920 frame.render_passes.push_back(RenderPass::Create());
7921 RenderPass* pass1 = frame.render_passes.back();
7923 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7924 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7925 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7927 frame.render_passes_by_id[pass1->id] = pass1;
7928 frame.render_passes_by_id[pass2->id] = pass2;
7929 frame.render_passes_by_id[pass3->id] = pass3;
7931 // Add a quad to each pass so they aren't empty.
7932 SolidColorDrawQuad* color_quad;
7933 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7934 color_quad->material = DrawQuad::SOLID_COLOR;
7935 color_quad = pass2->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7936 color_quad->material = DrawQuad::SOLID_COLOR;
7937 color_quad = pass3->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7938 color_quad->material = DrawQuad::SOLID_COLOR;
7940 // pass3 is referenced by pass2.
7941 RenderPassDrawQuad* rpdq =
7942 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7943 rpdq->material = DrawQuad::RENDER_PASS;
7944 rpdq->render_pass_id = pass3->id;
7946 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7947 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7948 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7949 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7950 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7951 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7952 EXPECT_EQ(1u, frame.render_passes.size());
7953 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7956 TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) {
7957 LayerTreeHostImpl::FrameData frame;
7958 frame.render_passes.push_back(RenderPass::Create());
7959 RenderPass* pass3 = frame.render_passes.back();
7960 frame.render_passes.push_back(RenderPass::Create());
7961 RenderPass* pass2 = frame.render_passes.back();
7962 frame.render_passes.push_back(RenderPass::Create());
7963 RenderPass* pass1 = frame.render_passes.back();
7965 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7966 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7967 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7969 frame.render_passes_by_id[pass1->id] = pass1;
7970 frame.render_passes_by_id[pass2->id] = pass2;
7971 frame.render_passes_by_id[pass3->id] = pass3;
7973 // pass1 is not empty, but pass2 and pass3 are.
7974 SolidColorDrawQuad* color_quad;
7975 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7976 color_quad->material = DrawQuad::SOLID_COLOR;
7978 // pass3 is referenced by pass2.
7979 RenderPassDrawQuad* rpdq =
7980 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7981 rpdq->material = DrawQuad::RENDER_PASS;
7982 rpdq->render_pass_id = pass3->id;
7984 // pass2 is referenced by pass1.
7985 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7986 rpdq->material = DrawQuad::RENDER_PASS;
7987 rpdq->render_pass_id = pass2->id;
7989 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7990 // should be removed.
7991 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7992 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7993 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7994 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7995 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7996 EXPECT_EQ(1u, frame.render_passes.size());
7997 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7998 // The RenderPassDrawQuad should be removed from pass1.
7999 EXPECT_EQ(1u, pass1->quad_list.size());
8000 EXPECT_EQ(DrawQuad::SOLID_COLOR, pass1->quad_list.ElementAt(0)->material);
8003 TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) {
8004 LayerTreeHostImpl::FrameData frame;
8005 frame.render_passes.push_back(RenderPass::Create());
8006 RenderPass* pass3 = frame.render_passes.back();
8007 frame.render_passes.push_back(RenderPass::Create());
8008 RenderPass* pass2 = frame.render_passes.back();
8009 frame.render_passes.push_back(RenderPass::Create());
8010 RenderPass* pass1 = frame.render_passes.back();
8012 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8013 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8014 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8016 frame.render_passes_by_id[pass1->id] = pass1;
8017 frame.render_passes_by_id[pass2->id] = pass2;
8018 frame.render_passes_by_id[pass3->id] = pass3;
8020 // pass3 is referenced by pass2.
8021 RenderPassDrawQuad* rpdq =
8022 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8023 rpdq->material = DrawQuad::RENDER_PASS;
8024 rpdq->render_pass_id = pass3->id;
8026 // pass2 is referenced by pass1.
8027 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
8028 rpdq->material = DrawQuad::RENDER_PASS;
8029 rpdq->render_pass_id = pass2->id;
8031 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8032 // should be removed. Then pass1 is empty too, but it's the root so it should
8033 // not be removed.
8034 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
8035 EXPECT_EQ(1u, frame.render_passes_by_id.size());
8036 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
8037 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
8038 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
8039 EXPECT_EQ(1u, frame.render_passes.size());
8040 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
8041 // The RenderPassDrawQuad should be removed from pass1.
8042 EXPECT_EQ(0u, pass1->quad_list.size());
8045 class FakeVideoFrameController : public VideoFrameController {
8046 public:
8047 void OnBeginFrame(const BeginFrameArgs& args) override {
8048 begin_frame_args_ = args;
8049 did_draw_frame_ = false;
8052 void DidDrawFrame() override { did_draw_frame_ = true; }
8054 const BeginFrameArgs& begin_frame_args() const { return begin_frame_args_; }
8056 bool did_draw_frame() const { return did_draw_frame_; }
8058 private:
8059 BeginFrameArgs begin_frame_args_;
8060 bool did_draw_frame_ = false;
8063 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
8064 host_impl_->DidFinishImplFrame();
8066 BeginFrameArgs begin_frame_args =
8067 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8068 FakeVideoFrameController controller;
8070 host_impl_->WillBeginImplFrame(begin_frame_args);
8071 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8072 host_impl_->AddVideoFrameController(&controller);
8073 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8074 host_impl_->DidFinishImplFrame();
8076 EXPECT_FALSE(controller.did_draw_frame());
8077 LayerTreeHostImpl::FrameData frame;
8078 host_impl_->DidDrawAllLayers(frame);
8079 EXPECT_TRUE(controller.did_draw_frame());
8081 controller.OnBeginFrame(begin_frame_args);
8082 EXPECT_FALSE(controller.did_draw_frame());
8083 host_impl_->RemoveVideoFrameController(&controller);
8084 host_impl_->DidDrawAllLayers(frame);
8085 EXPECT_FALSE(controller.did_draw_frame());
8088 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) {
8089 host_impl_->DidFinishImplFrame();
8091 BeginFrameArgs begin_frame_args =
8092 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8093 FakeVideoFrameController controller;
8095 host_impl_->WillBeginImplFrame(begin_frame_args);
8096 host_impl_->DidFinishImplFrame();
8098 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8099 host_impl_->AddVideoFrameController(&controller);
8100 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8102 begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8103 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8104 host_impl_->WillBeginImplFrame(begin_frame_args);
8105 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8107 EXPECT_FALSE(controller.did_draw_frame());
8108 LayerTreeHostImpl::FrameData frame;
8109 host_impl_->DidDrawAllLayers(frame);
8110 EXPECT_TRUE(controller.did_draw_frame());
8112 controller.OnBeginFrame(begin_frame_args);
8113 EXPECT_FALSE(controller.did_draw_frame());
8114 host_impl_->RemoveVideoFrameController(&controller);
8115 host_impl_->DidDrawAllLayers(frame);
8116 EXPECT_FALSE(controller.did_draw_frame());
8119 TEST_F(LayerTreeHostImplTest, GpuRasterizationStatusModes) {
8120 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8122 host_impl_->SetHasGpuRasterizationTrigger(true);
8123 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8124 EXPECT_EQ(GpuRasterizationStatus::ON, host_impl_->gpu_rasterization_status());
8125 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8127 host_impl_->SetHasGpuRasterizationTrigger(false);
8128 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8129 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT,
8130 host_impl_->gpu_rasterization_status());
8131 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8133 host_impl_->SetHasGpuRasterizationTrigger(true);
8134 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8135 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT,
8136 host_impl_->gpu_rasterization_status());
8137 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8138 EXPECT_FALSE(host_impl_->use_msaa());
8140 scoped_ptr<TestWebGraphicsContext3D> context_with_msaa =
8141 TestWebGraphicsContext3D::Create();
8142 context_with_msaa->SetMaxSamples(8);
8144 LayerTreeSettings msaaSettings = GpuRasterizationEnabledSettings();
8145 msaaSettings.gpu_rasterization_msaa_sample_count = 4;
8146 EXPECT_TRUE(CreateHostImpl(
8147 msaaSettings, FakeOutputSurface::Create3d(context_with_msaa.Pass())));
8148 host_impl_->SetHasGpuRasterizationTrigger(true);
8149 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8150 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT,
8151 host_impl_->gpu_rasterization_status());
8152 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8153 EXPECT_TRUE(host_impl_->use_msaa());
8155 LayerTreeSettings settings = DefaultSettings();
8156 settings.gpu_rasterization_enabled = false;
8157 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8158 host_impl_->SetHasGpuRasterizationTrigger(true);
8159 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8160 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE,
8161 host_impl_->gpu_rasterization_status());
8162 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8164 settings.gpu_rasterization_forced = true;
8165 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8167 host_impl_->SetHasGpuRasterizationTrigger(false);
8168 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8169 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED,
8170 host_impl_->gpu_rasterization_status());
8171 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8174 // A mock output surface which lets us detect calls to ForceReclaimResources.
8175 class MockReclaimResourcesOutputSurface : public FakeOutputSurface {
8176 public:
8177 static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() {
8178 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8179 TestContextProvider::Create(), TestContextProvider::Create(), false));
8182 MOCK_METHOD0(ForceReclaimResources, void());
8184 protected:
8185 MockReclaimResourcesOutputSurface(
8186 scoped_refptr<ContextProvider> context_provider,
8187 scoped_refptr<ContextProvider> worker_context_provider,
8188 bool delegated_rendering)
8189 : FakeOutputSurface(context_provider,
8190 worker_context_provider,
8191 delegated_rendering) {}
8194 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8195 // being reclaimed to block drawing between BeginCommit / Swap. This test
8196 // ensures that BeginCommit triggers ForceReclaimResources. See
8197 // crbug.com/489515.
8198 TEST_F(LayerTreeHostImplTest, BeginCommitReclaimsResources) {
8199 scoped_ptr<MockReclaimResourcesOutputSurface> output_surface(
8200 MockReclaimResourcesOutputSurface::Create3d());
8201 // Hold an unowned pointer to the output surface to use for mock expectations.
8202 MockReclaimResourcesOutputSurface* mock_output_surface = output_surface.get();
8204 CreateHostImpl(DefaultSettings(), output_surface.Pass());
8205 EXPECT_CALL(*mock_output_surface, ForceReclaimResources()).Times(1);
8206 host_impl_->BeginCommit();
8209 } // namespace
8210 } // namespace cc