Reland of Add channel-specific product logo to chrome://help (patchset #1 id:1 of...
[chromium-blink-merge.git] / cc / trees / layer_tree_host_impl_unittest.cc
blobb8dbc1ea10193e57c9854f3d4a1d5dc478b3ef0a
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.gpu_rasterization_enabled = true;
105 return settings;
108 void SetUp() override {
109 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
112 void TearDown() override {}
114 void UpdateRendererCapabilitiesOnImplThread() override {}
115 void DidLoseOutputSurfaceOnImplThread() override {}
116 void CommitVSyncParameters(base::TimeTicks timebase,
117 base::TimeDelta interval) override {}
118 void SetEstimatedParentDrawTime(base::TimeDelta draw_time) override {}
119 void SetMaxSwapsPendingOnImplThread(int max) override {}
120 void DidSwapBuffersOnImplThread() override {}
121 void DidSwapBuffersCompleteOnImplThread() override {}
122 void OnCanDrawStateChanged(bool can_draw) override {
123 on_can_draw_state_changed_called_ = true;
125 void NotifyReadyToActivate() override {
126 did_notify_ready_to_activate_ = true;
127 host_impl_->ActivateSyncTree();
129 void NotifyReadyToDraw() override {}
130 void SetNeedsRedrawOnImplThread() override { did_request_redraw_ = true; }
131 void SetNeedsRedrawRectOnImplThread(const gfx::Rect& damage_rect) override {
132 did_request_redraw_ = true;
134 void SetNeedsAnimateOnImplThread() override { did_request_animate_ = true; }
135 void SetNeedsPrepareTilesOnImplThread() override {
136 did_request_prepare_tiles_ = true;
138 void SetNeedsCommitOnImplThread() override { did_request_commit_ = true; }
139 void SetVideoNeedsBeginFrames(bool needs_begin_frames) override {}
140 void PostAnimationEventsToMainThreadOnImplThread(
141 scoped_ptr<AnimationEventsVector> events) override {}
142 bool IsInsideDraw() override { return false; }
143 void RenewTreePriority() override {}
144 void PostDelayedAnimationTaskOnImplThread(const base::Closure& task,
145 base::TimeDelta delay) override {
146 animation_task_ = task;
147 requested_animation_delay_ = delay;
149 void DidActivateSyncTree() override {}
150 void WillPrepareTiles() override {}
151 void DidPrepareTiles() override {}
152 void DidCompletePageScaleAnimationOnImplThread() override {
153 did_complete_page_scale_animation_ = true;
155 void OnDrawForOutputSurface() override {}
156 void PostFrameTimingEventsOnImplThread(
157 scoped_ptr<FrameTimingTracker::CompositeTimingSet> composite_events,
158 scoped_ptr<FrameTimingTracker::MainFrameTimingSet> main_frame_events)
159 override {}
161 void set_reduce_memory_result(bool reduce_memory_result) {
162 reduce_memory_result_ = reduce_memory_result;
165 virtual bool CreateHostImpl(const LayerTreeSettings& settings,
166 scoped_ptr<OutputSurface> output_surface) {
167 host_impl_ = LayerTreeHostImpl::Create(
168 settings, this, &proxy_, &stats_instrumentation_,
169 &shared_bitmap_manager_, &gpu_memory_buffer_manager_,
170 &task_graph_runner_, 0);
171 bool init = host_impl_->InitializeRenderer(output_surface.Pass());
172 host_impl_->SetViewportSize(gfx::Size(10, 10));
173 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
174 // Set the BeginFrameArgs so that methods which use it are able to.
175 host_impl_->WillBeginImplFrame(
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 scoped_ptr<LayerImpl> CreateScrollableLayer(int id,
335 const gfx::Size& size,
336 LayerImpl* clip_layer) {
337 DCHECK(clip_layer);
338 DCHECK(id != clip_layer->id());
339 scoped_ptr<LayerImpl> layer =
340 LayerImpl::Create(host_impl_->active_tree(), id);
341 layer->SetScrollClipLayer(clip_layer->id());
342 layer->SetDrawsContent(true);
343 layer->SetBounds(size);
344 clip_layer->SetBounds(gfx::Size(size.width() / 2, size.height() / 2));
345 return layer.Pass();
348 void DrawFrame() {
349 LayerTreeHostImpl::FrameData frame;
350 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
351 host_impl_->DrawLayers(&frame);
352 host_impl_->DidDrawAllLayers(frame);
355 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor);
356 void pinch_zoom_pan_viewport_test(float device_scale_factor);
357 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor);
358 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
359 float device_scale_factor);
361 void CheckNotifyCalledIfCanDrawChanged(bool always_draw) {
362 // Note: It is not possible to disable the renderer once it has been set,
363 // so we do not need to test that disabling the renderer notifies us
364 // that can_draw changed.
365 EXPECT_FALSE(host_impl_->CanDraw());
366 on_can_draw_state_changed_called_ = false;
368 // Set up the root layer, which allows us to draw.
369 SetupScrollAndContentsLayers(gfx::Size(100, 100));
370 EXPECT_TRUE(host_impl_->CanDraw());
371 EXPECT_TRUE(on_can_draw_state_changed_called_);
372 on_can_draw_state_changed_called_ = false;
374 // Toggle the root layer to make sure it toggles can_draw
375 host_impl_->active_tree()->SetRootLayer(nullptr);
376 EXPECT_FALSE(host_impl_->CanDraw());
377 EXPECT_TRUE(on_can_draw_state_changed_called_);
378 on_can_draw_state_changed_called_ = false;
380 SetupScrollAndContentsLayers(gfx::Size(100, 100));
381 EXPECT_TRUE(host_impl_->CanDraw());
382 EXPECT_TRUE(on_can_draw_state_changed_called_);
383 on_can_draw_state_changed_called_ = false;
385 // Toggle the device viewport size to make sure it toggles can_draw.
386 host_impl_->SetViewportSize(gfx::Size());
387 if (always_draw) {
388 EXPECT_TRUE(host_impl_->CanDraw());
389 } else {
390 EXPECT_FALSE(host_impl_->CanDraw());
392 EXPECT_TRUE(on_can_draw_state_changed_called_);
393 on_can_draw_state_changed_called_ = false;
395 host_impl_->SetViewportSize(gfx::Size(100, 100));
396 EXPECT_TRUE(host_impl_->CanDraw());
397 EXPECT_TRUE(on_can_draw_state_changed_called_);
398 on_can_draw_state_changed_called_ = false;
401 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor);
403 protected:
404 virtual scoped_ptr<OutputSurface> CreateOutputSurface() {
405 return FakeOutputSurface::Create3d();
408 void DrawOneFrame() {
409 LayerTreeHostImpl::FrameData frame_data;
410 host_impl_->PrepareToDraw(&frame_data);
411 host_impl_->DidDrawAllLayers(frame_data);
414 FakeProxy proxy_;
415 DebugScopedSetImplThread always_impl_thread_;
416 DebugScopedSetMainThreadBlocked always_main_thread_blocked_;
418 TestSharedBitmapManager shared_bitmap_manager_;
419 TestGpuMemoryBufferManager gpu_memory_buffer_manager_;
420 TestTaskGraphRunner task_graph_runner_;
421 scoped_ptr<LayerTreeHostImpl> host_impl_;
422 FakeRenderingStatsInstrumentation stats_instrumentation_;
423 bool on_can_draw_state_changed_called_;
424 bool did_notify_ready_to_activate_;
425 bool did_request_commit_;
426 bool did_request_redraw_;
427 bool did_request_animate_;
428 bool did_request_prepare_tiles_;
429 bool did_complete_page_scale_animation_;
430 bool reduce_memory_result_;
431 base::Closure animation_task_;
432 base::TimeDelta requested_animation_delay_;
435 // A test fixture for new animation timelines tests.
436 class LayerTreeHostImplTimelinesTest : public LayerTreeHostImplTest {
437 public:
438 void SetUp() override {
439 LayerTreeSettings settings = DefaultSettings();
440 settings.use_compositor_animation_timelines = true;
441 CreateHostImpl(settings, CreateOutputSurface());
445 TEST_F(LayerTreeHostImplTest, NotifyIfCanDrawChanged) {
446 bool always_draw = false;
447 CheckNotifyCalledIfCanDrawChanged(always_draw);
450 TEST_F(LayerTreeHostImplTest, CanDrawIncompleteFrames) {
451 CreateHostImpl(DefaultSettings(),
452 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
454 bool always_draw = true;
455 CheckNotifyCalledIfCanDrawChanged(always_draw);
458 TEST_F(LayerTreeHostImplTest, ScrollDeltaNoLayers) {
459 ASSERT_FALSE(host_impl_->active_tree()->root_layer());
461 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
462 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
465 TEST_F(LayerTreeHostImplTest, ScrollDeltaTreeButNoChanges) {
467 scoped_ptr<LayerImpl> root =
468 LayerImpl::Create(host_impl_->active_tree(), 1);
469 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 2));
470 root->AddChild(LayerImpl::Create(host_impl_->active_tree(), 3));
471 root->children()[1]->AddChild(
472 LayerImpl::Create(host_impl_->active_tree(), 4));
473 root->children()[1]->AddChild(
474 LayerImpl::Create(host_impl_->active_tree(), 5));
475 root->children()[1]->children()[0]->AddChild(
476 LayerImpl::Create(host_impl_->active_tree(), 6));
477 host_impl_->active_tree()->SetRootLayer(root.Pass());
479 LayerImpl* root = host_impl_->active_tree()->root_layer();
481 ExpectClearedScrollDeltasRecursive(root);
483 scoped_ptr<ScrollAndScaleSet> scroll_info;
485 scroll_info = host_impl_->ProcessScrollDeltas();
486 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
487 ExpectClearedScrollDeltasRecursive(root);
489 scroll_info = host_impl_->ProcessScrollDeltas();
490 ASSERT_EQ(scroll_info->scrolls.size(), 0u);
491 ExpectClearedScrollDeltasRecursive(root);
494 TEST_F(LayerTreeHostImplTest, ScrollDeltaRepeatedScrolls) {
495 gfx::ScrollOffset scroll_offset(20, 30);
496 gfx::Vector2d scroll_delta(11, -15);
498 scoped_ptr<LayerImpl> root_clip =
499 LayerImpl::Create(host_impl_->active_tree(), 2);
500 scoped_ptr<LayerImpl> root =
501 LayerImpl::Create(host_impl_->active_tree(), 1);
502 root_clip->SetBounds(gfx::Size(10, 10));
503 LayerImpl* root_layer = root.get();
504 root_clip->AddChild(root.Pass());
505 root_layer->SetBounds(gfx::Size(110, 110));
506 root_layer->SetScrollClipLayer(root_clip->id());
507 root_layer->PushScrollOffsetFromMainThread(scroll_offset);
508 root_layer->ScrollBy(scroll_delta);
509 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
511 LayerImpl* root = host_impl_->active_tree()->root_layer()->children()[0];
513 scoped_ptr<ScrollAndScaleSet> scroll_info;
515 scroll_info = host_impl_->ProcessScrollDeltas();
516 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
517 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(), scroll_delta));
519 gfx::Vector2d scroll_delta2(-5, 27);
520 root->ScrollBy(scroll_delta2);
521 scroll_info = host_impl_->ProcessScrollDeltas();
522 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
523 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(),
524 scroll_delta + scroll_delta2));
526 root->ScrollBy(gfx::Vector2d());
527 scroll_info = host_impl_->ProcessScrollDeltas();
528 EXPECT_TRUE(ScrollInfoContains(*scroll_info, root->id(),
529 scroll_delta + scroll_delta2));
532 TEST_F(LayerTreeHostImplTest, ScrollRootCallsCommitAndRedraw) {
533 SetupScrollAndContentsLayers(gfx::Size(100, 100));
534 host_impl_->SetViewportSize(gfx::Size(50, 50));
535 DrawFrame();
537 EXPECT_EQ(InputHandler::SCROLL_STARTED,
538 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
539 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
540 InputHandler::WHEEL));
541 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
542 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
543 InputHandler::WHEEL));
544 host_impl_->ScrollEnd();
545 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
546 InputHandler::WHEEL));
547 EXPECT_TRUE(did_request_redraw_);
548 EXPECT_TRUE(did_request_commit_);
551 TEST_F(LayerTreeHostImplTest, ScrollActiveOnlyAfterScrollMovement) {
552 SetupScrollAndContentsLayers(gfx::Size(100, 100));
553 host_impl_->SetViewportSize(gfx::Size(50, 50));
554 DrawFrame();
556 EXPECT_EQ(InputHandler::SCROLL_STARTED,
557 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
558 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
559 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
560 EXPECT_TRUE(host_impl_->IsActivelyScrolling());
561 host_impl_->ScrollEnd();
562 EXPECT_FALSE(host_impl_->IsActivelyScrolling());
565 TEST_F(LayerTreeHostImplTest, ScrollWithoutRootLayer) {
566 // We should not crash when trying to scroll an empty layer tree.
567 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
568 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
571 TEST_F(LayerTreeHostImplTest, ScrollWithoutRenderer) {
572 scoped_ptr<TestWebGraphicsContext3D> context_owned =
573 TestWebGraphicsContext3D::Create();
574 context_owned->set_context_lost(true);
576 // Initialization will fail.
577 EXPECT_FALSE(CreateHostImpl(
578 DefaultSettings(), FakeOutputSurface::Create3d(context_owned.Pass())));
580 SetupScrollAndContentsLayers(gfx::Size(100, 100));
582 // We should not crash when trying to scroll after the renderer initialization
583 // fails.
584 EXPECT_EQ(InputHandler::SCROLL_STARTED,
585 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
588 TEST_F(LayerTreeHostImplTest, ReplaceTreeWhileScrolling) {
589 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
590 host_impl_->SetViewportSize(gfx::Size(50, 50));
591 DrawFrame();
593 // We should not crash if the tree is replaced while we are scrolling.
594 EXPECT_EQ(InputHandler::SCROLL_STARTED,
595 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
596 host_impl_->active_tree()->DetachLayerTree();
598 scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
600 // We should still be scrolling, because the scrolled layer also exists in the
601 // new tree.
602 gfx::Vector2d scroll_delta(0, 10);
603 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
604 host_impl_->ScrollEnd();
605 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
606 EXPECT_TRUE(
607 ScrollInfoContains(*scroll_info, scroll_layer->id(), scroll_delta));
610 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnWheelEventHandlers) {
611 SetupScrollAndContentsLayers(gfx::Size(100, 100));
612 host_impl_->SetViewportSize(gfx::Size(50, 50));
613 DrawFrame();
614 LayerImpl* root = host_impl_->active_tree()->root_layer();
616 // With registered event handlers, wheel scrolls don't necessarily
617 // have to go to the main thread.
618 root->SetHaveWheelEventHandlers(true);
619 EXPECT_EQ(InputHandler::SCROLL_STARTED,
620 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
621 host_impl_->ScrollEnd();
623 // But typically the scroll-blocks-on mode will require them to.
624 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
625 SCROLL_BLOCKS_ON_START_TOUCH);
626 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
627 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
629 // But gesture scrolls can still be handled.
630 EXPECT_EQ(InputHandler::SCROLL_STARTED,
631 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
632 host_impl_->ScrollEnd();
634 // And if the handlers go away, wheel scrolls can again be processed
635 // on impl (despite the scroll-blocks-on mode).
636 root->SetHaveWheelEventHandlers(false);
637 EXPECT_EQ(InputHandler::SCROLL_STARTED,
638 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
639 host_impl_->ScrollEnd();
642 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnTouchEventHandlers) {
643 LayerImpl* scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
644 host_impl_->SetViewportSize(gfx::Size(50, 50));
645 DrawFrame();
646 LayerImpl* root = host_impl_->active_tree()->root_layer();
648 LayerImpl* child = 0;
650 scoped_ptr<LayerImpl> child_layer =
651 LayerImpl::Create(host_impl_->active_tree(), 6);
652 child = child_layer.get();
653 child_layer->SetDrawsContent(true);
654 child_layer->SetPosition(gfx::PointF(0, 20));
655 child_layer->SetBounds(gfx::Size(50, 50));
656 scroll->AddChild(child_layer.Pass());
659 // Touch handler regions determine whether touch events block scroll.
660 root->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
661 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
662 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH |
663 SCROLL_BLOCKS_ON_WHEEL_EVENT);
664 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
666 // But they don't influence the actual handling of the scroll gestures.
667 EXPECT_EQ(InputHandler::SCROLL_STARTED,
668 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
669 host_impl_->ScrollEnd();
671 // It's the union of scroll-blocks-on mode bits across all layers in the
672 // scroll paret chain that matters.
673 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
674 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE);
675 EXPECT_FALSE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
676 child->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH);
677 EXPECT_TRUE(host_impl_->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
680 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnScrollEventHandlers) {
681 SetupScrollAndContentsLayers(gfx::Size(100, 100));
682 host_impl_->SetViewportSize(gfx::Size(50, 50));
683 DrawFrame();
684 LayerImpl* root = host_impl_->active_tree()->root_layer();
686 // With registered scroll handlers, scrolls don't generally have to go
687 // to the main thread.
688 root->SetHaveScrollEventHandlers(true);
689 EXPECT_EQ(InputHandler::SCROLL_STARTED,
690 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
691 host_impl_->ScrollEnd();
693 // Even the default scroll blocks on mode doesn't require this.
694 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT |
695 SCROLL_BLOCKS_ON_START_TOUCH);
696 EXPECT_EQ(InputHandler::SCROLL_STARTED,
697 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
698 host_impl_->ScrollEnd();
700 // But the page can opt in to blocking on scroll event handlers.
701 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
702 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
703 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
705 // GESTURE and WHEEL scrolls behave identically in this regard.
706 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
707 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
709 // And if the handlers go away, scrolls can again be processed on impl
710 // (despite the scroll-blocks-on mode).
711 root->SetHaveScrollEventHandlers(false);
712 EXPECT_EQ(InputHandler::SCROLL_STARTED,
713 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
714 host_impl_->ScrollEnd();
717 TEST_F(LayerTreeHostImplTest, ScrollBlocksOnLayerTopology) {
718 host_impl_->SetViewportSize(gfx::Size(50, 50));
720 // Create a normal scrollable root layer
721 LayerImpl* root_scroll = SetupScrollAndContentsLayers(gfx::Size(100, 100));
722 LayerImpl* root_child = root_scroll->children()[0];
723 LayerImpl* root = host_impl_->active_tree()->root_layer();
724 DrawFrame();
726 // Create two child scrollable layers
727 LayerImpl* child1 = 0;
729 scoped_ptr<LayerImpl> scrollable_child_clip_1 =
730 LayerImpl::Create(host_impl_->active_tree(), 6);
731 scoped_ptr<LayerImpl> scrollable_child_1 = CreateScrollableLayer(
732 7, gfx::Size(10, 10), scrollable_child_clip_1.get());
733 child1 = scrollable_child_1.get();
734 scrollable_child_1->SetPosition(gfx::Point(5, 5));
735 scrollable_child_1->SetHaveWheelEventHandlers(true);
736 scrollable_child_1->SetHaveScrollEventHandlers(true);
737 scrollable_child_clip_1->AddChild(scrollable_child_1.Pass());
738 root_child->AddChild(scrollable_child_clip_1.Pass());
741 LayerImpl* child2 = 0;
743 scoped_ptr<LayerImpl> scrollable_child_clip_2 =
744 LayerImpl::Create(host_impl_->active_tree(), 8);
745 scoped_ptr<LayerImpl> scrollable_child_2 = CreateScrollableLayer(
746 9, gfx::Size(10, 10), scrollable_child_clip_2.get());
747 child2 = scrollable_child_2.get();
748 scrollable_child_2->SetPosition(gfx::Point(5, 20));
749 scrollable_child_2->SetHaveWheelEventHandlers(true);
750 scrollable_child_2->SetHaveScrollEventHandlers(true);
751 scrollable_child_clip_2->AddChild(scrollable_child_2.Pass());
752 root_child->AddChild(scrollable_child_clip_2.Pass());
755 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
756 EXPECT_EQ(InputHandler::SCROLL_STARTED,
757 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
758 host_impl_->ScrollEnd();
759 child1->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
760 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
761 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE));
763 // But not those that hit only other layers.
764 EXPECT_EQ(InputHandler::SCROLL_STARTED,
765 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
766 host_impl_->ScrollEnd();
768 // It's the union of bits set across the scroll ancestor chain that matters.
769 EXPECT_EQ(InputHandler::SCROLL_STARTED,
770 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
771 host_impl_->ScrollEnd();
772 EXPECT_EQ(InputHandler::SCROLL_STARTED,
773 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
774 host_impl_->ScrollEnd();
775 root->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT);
776 EXPECT_EQ(InputHandler::SCROLL_STARTED,
777 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
778 host_impl_->ScrollEnd();
779 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
780 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
781 child2->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT);
782 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
783 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL));
784 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
785 host_impl_->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE));
788 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchscreen) {
789 SetupScrollAndContentsLayers(gfx::Size(100, 100));
790 host_impl_->SetViewportSize(gfx::Size(50, 50));
791 DrawFrame();
793 // Ignore the fling since no layer is being scrolled
794 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
796 // Start scrolling a layer
797 EXPECT_EQ(InputHandler::SCROLL_STARTED,
798 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
800 // Now the fling should go ahead since we've started scrolling a layer
801 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
804 TEST_F(LayerTreeHostImplTest, FlingOnlyWhenScrollingTouchpad) {
805 SetupScrollAndContentsLayers(gfx::Size(100, 100));
806 host_impl_->SetViewportSize(gfx::Size(50, 50));
807 DrawFrame();
809 // Ignore the fling since no layer is being scrolled
810 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
812 // Start scrolling a layer
813 EXPECT_EQ(InputHandler::SCROLL_STARTED,
814 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
816 // Now the fling should go ahead since we've started scrolling a layer
817 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
820 TEST_F(LayerTreeHostImplTest, NoFlingWhenScrollingOnMain) {
821 SetupScrollAndContentsLayers(gfx::Size(100, 100));
822 host_impl_->SetViewportSize(gfx::Size(50, 50));
823 DrawFrame();
824 LayerImpl* root = host_impl_->active_tree()->root_layer();
826 root->SetShouldScrollOnMainThread(true);
828 // Start scrolling a layer
829 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
830 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
832 // The fling should be ignored since there's no layer being scrolled impl-side
833 EXPECT_EQ(InputHandler::SCROLL_IGNORED, host_impl_->FlingScrollBegin());
836 TEST_F(LayerTreeHostImplTest, ShouldScrollOnMainThread) {
837 SetupScrollAndContentsLayers(gfx::Size(100, 100));
838 host_impl_->SetViewportSize(gfx::Size(50, 50));
839 DrawFrame();
840 LayerImpl* root = host_impl_->active_tree()->root_layer();
842 root->SetShouldScrollOnMainThread(true);
844 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
845 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
846 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
847 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
850 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionBasic) {
851 SetupScrollAndContentsLayers(gfx::Size(200, 200));
852 host_impl_->SetViewportSize(gfx::Size(100, 100));
854 LayerImpl* root = host_impl_->active_tree()->root_layer();
855 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
857 DrawFrame();
859 // All scroll types inside the non-fast scrollable region should fail.
860 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
861 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL));
862 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
863 InputHandler::WHEEL));
864 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
865 host_impl_->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE));
866 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
867 InputHandler::GESTURE));
869 // All scroll types outside this region should succeed.
870 EXPECT_EQ(InputHandler::SCROLL_STARTED,
871 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL));
872 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
873 InputHandler::GESTURE));
874 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
875 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
876 InputHandler::GESTURE));
877 host_impl_->ScrollEnd();
878 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
879 InputHandler::GESTURE));
880 EXPECT_EQ(InputHandler::SCROLL_STARTED,
881 host_impl_->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE));
882 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
883 InputHandler::GESTURE));
884 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
885 host_impl_->ScrollEnd();
886 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
887 InputHandler::GESTURE));
890 TEST_F(LayerTreeHostImplTest, NonFastScrollableRegionWithOffset) {
891 SetupScrollAndContentsLayers(gfx::Size(200, 200));
892 host_impl_->SetViewportSize(gfx::Size(100, 100));
894 LayerImpl* root = host_impl_->active_tree()->root_layer();
895 root->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
896 root->SetPosition(gfx::PointF(-25.f, 0.f));
898 DrawFrame();
900 // This point would fall into the non-fast scrollable region except that we've
901 // moved the layer down by 25 pixels.
902 EXPECT_EQ(InputHandler::SCROLL_STARTED,
903 host_impl_->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL));
904 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
905 InputHandler::WHEEL));
906 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
907 host_impl_->ScrollEnd();
909 // This point is still inside the non-fast region.
910 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
911 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL));
914 TEST_F(LayerTreeHostImplTest, ScrollHandlerNotPresent) {
915 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
916 EXPECT_FALSE(scroll_layer->have_scroll_event_handlers());
917 host_impl_->SetViewportSize(gfx::Size(50, 50));
918 DrawFrame();
920 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
921 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
922 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
923 host_impl_->ScrollEnd();
924 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
927 TEST_F(LayerTreeHostImplTest, ScrollHandlerPresent) {
928 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
929 scroll_layer->SetHaveScrollEventHandlers(true);
930 host_impl_->SetViewportSize(gfx::Size(50, 50));
931 DrawFrame();
933 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
934 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
935 EXPECT_TRUE(host_impl_->scroll_affects_scroll_handler());
936 host_impl_->ScrollEnd();
937 EXPECT_FALSE(host_impl_->scroll_affects_scroll_handler());
940 TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) {
941 SetupScrollAndContentsLayers(gfx::Size(200, 200));
942 host_impl_->SetViewportSize(gfx::Size(100, 100));
944 DrawFrame();
946 EXPECT_EQ(InputHandler::SCROLL_STARTED,
947 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
949 // Trying to scroll to the left/top will not succeed.
950 EXPECT_FALSE(
951 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
952 EXPECT_FALSE(
953 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
954 EXPECT_FALSE(
955 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
957 // Scrolling to the right/bottom will succeed.
958 EXPECT_TRUE(
959 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll);
960 EXPECT_TRUE(
961 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
962 EXPECT_TRUE(
963 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll);
965 // Scrolling to left/top will now succeed.
966 EXPECT_TRUE(
967 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
968 EXPECT_TRUE(
969 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll);
970 EXPECT_TRUE(
971 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll);
973 // Scrolling diagonally against an edge will succeed.
974 EXPECT_TRUE(
975 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll);
976 EXPECT_TRUE(
977 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll);
978 EXPECT_TRUE(
979 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll);
981 // Trying to scroll more than the available space will also succeed.
982 EXPECT_TRUE(
983 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll);
986 TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) {
987 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
988 host_impl_->SetViewportSize(gfx::Size(100, 1000));
990 DrawFrame();
992 EXPECT_EQ(InputHandler::SCROLL_STARTED,
993 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
995 // Trying to scroll without a vertical scrollbar will fail.
996 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
997 gfx::Point(), SCROLL_FORWARD));
998 EXPECT_FALSE(host_impl_->ScrollVerticallyByPage(
999 gfx::Point(), SCROLL_BACKWARD));
1001 scoped_ptr<PaintedScrollbarLayerImpl> vertical_scrollbar(
1002 PaintedScrollbarLayerImpl::Create(
1003 host_impl_->active_tree(),
1005 VERTICAL));
1006 vertical_scrollbar->SetBounds(gfx::Size(15, 1000));
1007 host_impl_->InnerViewportScrollLayer()->AddScrollbar(
1008 vertical_scrollbar.get());
1010 // Trying to scroll with a vertical scrollbar will succeed.
1011 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1012 gfx::Point(), SCROLL_FORWARD));
1013 EXPECT_FLOAT_EQ(875.f,
1014 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
1015 EXPECT_TRUE(host_impl_->ScrollVerticallyByPage(
1016 gfx::Point(), SCROLL_BACKWARD));
1019 TEST_F(LayerTreeHostImplTest, ScrollWithUserUnscrollableLayers) {
1020 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(200, 200));
1021 host_impl_->SetViewportSize(gfx::Size(100, 100));
1023 gfx::Size overflow_size(400, 400);
1024 ASSERT_EQ(1u, scroll_layer->children().size());
1025 LayerImpl* overflow = scroll_layer->children()[0];
1026 overflow->SetBounds(overflow_size);
1027 overflow->SetScrollClipLayer(scroll_layer->parent()->id());
1028 overflow->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1029 overflow->SetPosition(gfx::PointF());
1031 DrawFrame();
1032 gfx::Point scroll_position(10, 10);
1034 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1035 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1036 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1037 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow->CurrentScrollOffset());
1039 gfx::Vector2dF scroll_delta(10, 10);
1040 host_impl_->ScrollBy(scroll_position, scroll_delta);
1041 host_impl_->ScrollEnd();
1042 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1043 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1045 overflow->set_user_scrollable_horizontal(false);
1047 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1048 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1049 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
1050 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow->CurrentScrollOffset());
1052 host_impl_->ScrollBy(scroll_position, scroll_delta);
1053 host_impl_->ScrollEnd();
1054 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1055 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1057 overflow->set_user_scrollable_vertical(false);
1059 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1060 host_impl_->ScrollBegin(scroll_position, InputHandler::WHEEL));
1061 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer->CurrentScrollOffset());
1062 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1064 host_impl_->ScrollBy(scroll_position, scroll_delta);
1065 host_impl_->ScrollEnd();
1066 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer->CurrentScrollOffset());
1067 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow->CurrentScrollOffset());
1070 TEST_F(LayerTreeHostImplTest, ImplPinchZoom) {
1071 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
1072 host_impl_->SetViewportSize(gfx::Size(50, 50));
1073 DrawFrame();
1075 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
1076 LayerImpl* container_layer = scroll_layer->scroll_clip_layer();
1077 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1079 float min_page_scale = 1.f, max_page_scale = 4.f;
1080 float page_scale_factor = 1.f;
1082 // The impl-based pinch zoom should adjust the max scroll position.
1084 host_impl_->active_tree()->PushPageScaleFromMainThread(
1085 page_scale_factor, min_page_scale, max_page_scale);
1086 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1087 scroll_layer->SetScrollDelta(gfx::Vector2d());
1089 float page_scale_delta = 2.f;
1091 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1092 host_impl_->PinchGestureBegin();
1093 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1094 host_impl_->PinchGestureEnd();
1095 host_impl_->ScrollEnd();
1096 EXPECT_FALSE(did_request_animate_);
1097 EXPECT_TRUE(did_request_redraw_);
1098 EXPECT_TRUE(did_request_commit_);
1099 EXPECT_EQ(gfx::Size(50, 50), container_layer->bounds());
1101 scoped_ptr<ScrollAndScaleSet> scroll_info =
1102 host_impl_->ProcessScrollDeltas();
1103 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1105 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1106 scroll_layer->MaxScrollOffset().ToString());
1109 // Scrolling after a pinch gesture should always be in local space. The
1110 // scroll deltas have the page scale factor applied.
1112 host_impl_->active_tree()->PushPageScaleFromMainThread(
1113 page_scale_factor, min_page_scale, max_page_scale);
1114 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1115 scroll_layer->SetScrollDelta(gfx::Vector2d());
1117 float page_scale_delta = 2.f;
1118 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1119 host_impl_->PinchGestureBegin();
1120 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1121 host_impl_->PinchGestureEnd();
1122 host_impl_->ScrollEnd();
1124 gfx::Vector2d scroll_delta(0, 10);
1125 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1126 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
1127 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
1128 host_impl_->ScrollEnd();
1130 scoped_ptr<ScrollAndScaleSet> scroll_info =
1131 host_impl_->ProcessScrollDeltas();
1132 EXPECT_TRUE(ScrollInfoContains(
1133 *scroll_info.get(), scroll_layer->id(),
1134 gfx::Vector2d(0, scroll_delta.y() / page_scale_delta)));
1138 TEST_F(LayerTreeHostImplTest, ViewportScrollOrder) {
1139 LayerTreeSettings settings = DefaultSettings();
1140 settings.invert_viewport_scroll_order = true;
1141 CreateHostImpl(settings,
1142 CreateOutputSurface());
1143 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.25f, 4.f);
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.f, gfx::Point(0, 0));
1159 host_impl_->PinchGestureEnd();
1160 host_impl_->ScrollEnd();
1162 // Sanity check - we're zoomed in, starting from the origin.
1163 EXPECT_VECTOR_EQ(
1164 gfx::Vector2dF(0, 0),
1165 outer_scroll_layer->CurrentScrollOffset());
1166 EXPECT_VECTOR_EQ(
1167 gfx::Vector2dF(0, 0),
1168 inner_scroll_layer->CurrentScrollOffset());
1170 // Scroll down - only the inner viewport should scroll.
1171 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1172 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f, 100.f));
1173 host_impl_->ScrollEnd();
1175 EXPECT_VECTOR_EQ(
1176 gfx::Vector2dF(50, 50),
1177 inner_scroll_layer->CurrentScrollOffset());
1178 EXPECT_VECTOR_EQ(
1179 gfx::Vector2dF(0, 0),
1180 outer_scroll_layer->CurrentScrollOffset());
1182 // Scroll down - outer viewport should start scrolling after the inner is at
1183 // its maximum.
1184 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1185 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f, 1000.f));
1186 host_impl_->ScrollEnd();
1188 EXPECT_VECTOR_EQ(
1189 gfx::Vector2dF(250, 250),
1190 inner_scroll_layer->CurrentScrollOffset());
1191 EXPECT_VECTOR_EQ(
1192 gfx::Vector2dF(300, 300),
1193 outer_scroll_layer->CurrentScrollOffset());
1196 TEST_F(LayerTreeHostImplTest, ScrollDuringPinchScrollsInnerViewport) {
1197 LayerTreeSettings settings = DefaultSettings();
1198 settings.invert_viewport_scroll_order = true;
1199 CreateHostImpl(settings,
1200 CreateOutputSurface());
1201 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
1203 const gfx::Size content_size(1000, 1000);
1204 const gfx::Size viewport_size(500, 500);
1205 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1207 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1208 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1210 EXPECT_VECTOR_EQ(
1211 gfx::Vector2dF(500, 500),
1212 outer_scroll_layer->MaxScrollOffset());
1214 host_impl_->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE);
1215 host_impl_->PinchGestureBegin();
1216 host_impl_->PinchGestureUpdate(2, gfx::Point(250, 250));
1217 host_impl_->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f, 10.f));
1218 host_impl_->PinchGestureEnd();
1219 host_impl_->ScrollEnd();
1221 EXPECT_VECTOR_EQ(
1222 gfx::Vector2dF(0, 0),
1223 outer_scroll_layer->CurrentScrollOffset());
1224 EXPECT_VECTOR_EQ(
1225 gfx::Vector2dF(130, 130),
1226 inner_scroll_layer->CurrentScrollOffset());
1229 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1230 // a pinch zoom is anchored within a certain margin of the screen edge, we
1231 // should assume the user means to scroll into the edge of the screen.
1232 TEST_F(LayerTreeHostImplTest, PinchZoomSnapsToScreenEdge) {
1233 LayerTreeSettings settings = DefaultSettings();
1234 settings.invert_viewport_scroll_order = true;
1235 CreateHostImpl(settings,
1236 CreateOutputSurface());
1237 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
1239 const gfx::Size content_size(1000, 1000);
1240 const gfx::Size viewport_size(500, 500);
1241 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1243 int offsetFromEdge = Viewport::kPinchZoomSnapMarginDips - 5;
1244 gfx::Point anchor(viewport_size.width() - offsetFromEdge,
1245 viewport_size.height() - offsetFromEdge);
1247 // Pinch in within the margins. The scroll should stay exactly locked to the
1248 // bottom and right.
1249 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1250 host_impl_->PinchGestureBegin();
1251 host_impl_->PinchGestureUpdate(2, anchor);
1252 host_impl_->PinchGestureEnd();
1253 host_impl_->ScrollEnd();
1255 EXPECT_VECTOR_EQ(
1256 gfx::Vector2dF(250, 250),
1257 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1259 // Reset.
1260 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1261 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1262 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1264 // Pinch in within the margins. The scroll should stay exactly locked to the
1265 // top and left.
1266 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1267 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1268 host_impl_->PinchGestureBegin();
1269 host_impl_->PinchGestureUpdate(2, anchor);
1270 host_impl_->PinchGestureEnd();
1271 host_impl_->ScrollEnd();
1273 EXPECT_VECTOR_EQ(
1274 gfx::Vector2dF(0, 0),
1275 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1277 // Reset.
1278 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1279 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1280 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1282 // Pinch in just outside the margin. There should be no snapping.
1283 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1284 anchor = gfx::Point(offsetFromEdge, offsetFromEdge);
1285 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1286 host_impl_->PinchGestureBegin();
1287 host_impl_->PinchGestureUpdate(2, anchor);
1288 host_impl_->PinchGestureEnd();
1289 host_impl_->ScrollEnd();
1291 EXPECT_VECTOR_EQ(
1292 gfx::Vector2dF(50, 50),
1293 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1295 // Reset.
1296 host_impl_->active_tree()->SetPageScaleOnActiveTree(1.f);
1297 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1298 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1300 // Pinch in just outside the margin. There should be no snapping.
1301 offsetFromEdge = Viewport::kPinchZoomSnapMarginDips;
1302 anchor = gfx::Point(viewport_size.width() - offsetFromEdge,
1303 viewport_size.height() - offsetFromEdge);
1304 host_impl_->ScrollBegin(anchor, InputHandler::GESTURE);
1305 host_impl_->PinchGestureBegin();
1306 host_impl_->PinchGestureUpdate(2, anchor);
1307 host_impl_->PinchGestureEnd();
1308 host_impl_->ScrollEnd();
1310 EXPECT_VECTOR_EQ(
1311 gfx::Vector2dF(200, 200),
1312 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1315 TEST_F(LayerTreeHostImplTest, ImplPinchZoomWheelBubbleBetweenViewports) {
1316 const gfx::Size content_size(200, 200);
1317 const gfx::Size viewport_size(100, 100);
1318 CreateBasicVirtualViewportLayers(viewport_size, content_size);
1320 LayerImpl* outer_scroll_layer = host_impl_->OuterViewportScrollLayer();
1321 LayerImpl* inner_scroll_layer = host_impl_->InnerViewportScrollLayer();
1323 // Zoom into the page by a 2X factor
1324 float min_page_scale = 1.f, max_page_scale = 4.f;
1325 float page_scale_factor = 2.f;
1326 host_impl_->active_tree()->PushPageScaleFromMainThread(
1327 page_scale_factor, min_page_scale, max_page_scale);
1328 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
1330 // Scroll by a small amount, there should be no bubbling up to the inner
1331 // viewport.
1332 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1333 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f, 20.f));
1334 host_impl_->ScrollEnd();
1336 EXPECT_VECTOR_EQ(
1337 gfx::Vector2dF(5, 10),
1338 outer_scroll_layer->CurrentScrollOffset());
1339 EXPECT_VECTOR_EQ(
1340 gfx::Vector2dF(),
1341 inner_scroll_layer->CurrentScrollOffset());
1343 // Scroll by the outer viewport's max scroll extent, there the remainder
1344 // should bubble up to the inner viewport.
1345 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1346 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f, 200.f));
1347 host_impl_->ScrollEnd();
1349 EXPECT_VECTOR_EQ(
1350 gfx::Vector2dF(100, 100),
1351 outer_scroll_layer->CurrentScrollOffset());
1352 EXPECT_VECTOR_EQ(
1353 gfx::Vector2dF(5, 10),
1354 inner_scroll_layer->CurrentScrollOffset());
1356 // Scroll by the inner viewport's max scroll extent, it should all go to the
1357 // inner viewport.
1358 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL);
1359 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f, 80.f));
1360 host_impl_->ScrollEnd();
1362 EXPECT_VECTOR_EQ(
1363 gfx::Vector2dF(100, 100),
1364 outer_scroll_layer->CurrentScrollOffset());
1365 EXPECT_VECTOR_EQ(
1366 gfx::Vector2dF(50, 50),
1367 inner_scroll_layer->CurrentScrollOffset());
1370 TEST_F(LayerTreeHostImplTest, ScrollWithSwapPromises) {
1371 ui::LatencyInfo latency_info;
1372 latency_info.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
1373 1234);
1374 scoped_ptr<SwapPromise> swap_promise(
1375 new LatencyInfoSwapPromise(latency_info));
1377 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1378 EXPECT_EQ(InputHandler::SCROLL_STARTED,
1379 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
1380 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1381 host_impl_->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise.Pass());
1382 host_impl_->ScrollEnd();
1384 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
1385 EXPECT_EQ(1u, scroll_info->swap_promises.size());
1386 EXPECT_EQ(latency_info.trace_id(), scroll_info->swap_promises[0]->TraceId());
1389 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1390 // up to the scroll_parent, rather than the stacking parent.
1391 TEST_F(LayerTreeHostImplTest, ScrollBubblesToScrollParent) {
1392 LayerImpl* viewport_scroll =
1393 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1394 host_impl_->SetViewportSize(gfx::Size(50, 50));
1396 // Set up two scrolling children of the root, one of which is a scroll parent
1397 // to the other. Scrolls bubbling from the child should bubble to the parent,
1398 // not the viewport.
1399 LayerImpl *parent;
1400 LayerImpl *child;
1401 LayerImpl *child_clip;
1403 scoped_ptr<LayerImpl> scroll_parent_clip =
1404 LayerImpl::Create(host_impl_->active_tree(), 6);
1405 scoped_ptr<LayerImpl> scroll_parent = CreateScrollableLayer(
1406 7, gfx::Size(10, 10), scroll_parent_clip.get());
1407 parent = scroll_parent.get();
1408 scroll_parent_clip->AddChild(scroll_parent.Pass());
1410 viewport_scroll->AddChild(scroll_parent_clip.Pass());
1412 scoped_ptr<LayerImpl> scroll_child_clip =
1413 LayerImpl::Create(host_impl_->active_tree(), 8);
1414 scoped_ptr<LayerImpl> scroll_child = CreateScrollableLayer(
1415 9, gfx::Size(10, 10), scroll_child_clip.get());
1416 child = scroll_child.get();
1417 scroll_child->SetPosition(gfx::Point(20, 20));
1418 scroll_child_clip->AddChild(scroll_child.Pass());
1420 child_clip = scroll_child_clip.get();
1421 viewport_scroll->AddChild(scroll_child_clip.Pass());
1423 child_clip->SetScrollParent(parent);
1425 DrawFrame();
1428 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1429 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1430 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1431 host_impl_->ScrollEnd();
1433 // The child should be fully scrolled by the first ScrollBy.
1434 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child->CurrentScrollOffset());
1436 // The scroll_parent should receive the bubbled up second ScrollBy.
1437 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent->CurrentScrollOffset());
1439 // The viewport shouldn't have been scrolled at all.
1440 EXPECT_VECTOR_EQ(
1441 gfx::Vector2dF(0, 0),
1442 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1443 EXPECT_VECTOR_EQ(
1444 gfx::Vector2dF(0, 0),
1445 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1449 host_impl_->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE);
1450 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1451 host_impl_->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1452 host_impl_->ScrollEnd();
1454 // The first ScrollBy should scroll the parent to its extent.
1455 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent->CurrentScrollOffset());
1457 // The viewport should now be next in bubbling order.
1458 EXPECT_VECTOR_EQ(
1459 gfx::Vector2dF(2, 1),
1460 host_impl_->InnerViewportScrollLayer()->CurrentScrollOffset());
1461 EXPECT_VECTOR_EQ(
1462 gfx::Vector2dF(0, 0),
1463 host_impl_->OuterViewportScrollLayer()->CurrentScrollOffset());
1468 TEST_F(LayerTreeHostImplTest, PinchGesture) {
1469 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1470 host_impl_->SetViewportSize(gfx::Size(50, 50));
1471 DrawFrame();
1473 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1474 DCHECK(scroll_layer);
1476 float min_page_scale = 1.f;
1477 float max_page_scale = 4.f;
1479 // Basic pinch zoom in gesture
1481 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1482 max_page_scale);
1483 scroll_layer->SetScrollDelta(gfx::Vector2d());
1485 float page_scale_delta = 2.f;
1486 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1487 host_impl_->PinchGestureBegin();
1488 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1489 host_impl_->PinchGestureEnd();
1490 host_impl_->ScrollEnd();
1491 EXPECT_FALSE(did_request_animate_);
1492 EXPECT_TRUE(did_request_redraw_);
1493 EXPECT_TRUE(did_request_commit_);
1495 scoped_ptr<ScrollAndScaleSet> scroll_info =
1496 host_impl_->ProcessScrollDeltas();
1497 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1500 // Zoom-in clamping
1502 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1503 max_page_scale);
1504 scroll_layer->SetScrollDelta(gfx::Vector2d());
1505 float page_scale_delta = 10.f;
1507 host_impl_->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE);
1508 host_impl_->PinchGestureBegin();
1509 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(50, 50));
1510 host_impl_->PinchGestureEnd();
1511 host_impl_->ScrollEnd();
1513 scoped_ptr<ScrollAndScaleSet> scroll_info =
1514 host_impl_->ProcessScrollDeltas();
1515 EXPECT_EQ(scroll_info->page_scale_delta, max_page_scale);
1518 // Zoom-out clamping
1520 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1521 max_page_scale);
1522 scroll_layer->SetScrollDelta(gfx::Vector2d());
1523 scroll_layer->PullDeltaForMainThread();
1524 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1526 float page_scale_delta = 0.1f;
1527 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
1528 host_impl_->PinchGestureBegin();
1529 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
1530 host_impl_->PinchGestureEnd();
1531 host_impl_->ScrollEnd();
1533 scoped_ptr<ScrollAndScaleSet> scroll_info =
1534 host_impl_->ProcessScrollDeltas();
1535 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1537 EXPECT_TRUE(scroll_info->scrolls.empty());
1540 // Two-finger panning should not happen based on pinch events only
1542 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1543 max_page_scale);
1544 scroll_layer->SetScrollDelta(gfx::Vector2d());
1545 scroll_layer->PullDeltaForMainThread();
1546 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1548 float page_scale_delta = 1.f;
1549 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1550 host_impl_->PinchGestureBegin();
1551 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1552 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1553 host_impl_->PinchGestureEnd();
1554 host_impl_->ScrollEnd();
1556 scoped_ptr<ScrollAndScaleSet> scroll_info =
1557 host_impl_->ProcessScrollDeltas();
1558 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1559 EXPECT_TRUE(scroll_info->scrolls.empty());
1562 // Two-finger panning should work with interleaved scroll events
1564 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1565 max_page_scale);
1566 scroll_layer->SetScrollDelta(gfx::Vector2d());
1567 scroll_layer->PullDeltaForMainThread();
1568 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1570 float page_scale_delta = 1.f;
1571 host_impl_->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE);
1572 host_impl_->PinchGestureBegin();
1573 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(10, 10));
1574 host_impl_->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1575 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point(20, 20));
1576 host_impl_->PinchGestureEnd();
1577 host_impl_->ScrollEnd();
1579 scoped_ptr<ScrollAndScaleSet> scroll_info =
1580 host_impl_->ProcessScrollDeltas();
1581 EXPECT_EQ(scroll_info->page_scale_delta, page_scale_delta);
1582 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1583 gfx::Vector2d(-10, -10)));
1586 // Two-finger panning should work when starting fully zoomed out.
1588 host_impl_->active_tree()->PushPageScaleFromMainThread(0.5f, 0.5f, 4.f);
1589 scroll_layer->SetScrollDelta(gfx::Vector2d());
1590 scroll_layer->PullDeltaForMainThread();
1591 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1593 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE);
1594 host_impl_->PinchGestureBegin();
1595 host_impl_->PinchGestureUpdate(2.f, gfx::Point(0, 0));
1596 host_impl_->PinchGestureUpdate(1.f, gfx::Point(0, 0));
1597 host_impl_->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1598 host_impl_->PinchGestureUpdate(1.f, gfx::Point(10, 10));
1599 host_impl_->PinchGestureEnd();
1600 host_impl_->ScrollEnd();
1602 scoped_ptr<ScrollAndScaleSet> scroll_info =
1603 host_impl_->ProcessScrollDeltas();
1604 EXPECT_EQ(scroll_info->page_scale_delta, 2.f);
1605 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1606 gfx::Vector2d(20, 20)));
1610 TEST_F(LayerTreeHostImplTest, PageScaleAnimation) {
1611 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1612 host_impl_->SetViewportSize(gfx::Size(50, 50));
1613 DrawFrame();
1615 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1616 DCHECK(scroll_layer);
1618 float min_page_scale = 0.5f;
1619 float max_page_scale = 4.f;
1620 base::TimeTicks start_time = base::TimeTicks() +
1621 base::TimeDelta::FromSeconds(1);
1622 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1623 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1624 base::TimeTicks end_time = start_time + duration;
1626 // Non-anchor zoom-in
1628 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1629 max_page_scale);
1630 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1632 did_request_redraw_ = false;
1633 did_request_animate_ = false;
1634 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1635 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1636 gfx::Vector2d(),
1637 false,
1638 2.f,
1639 duration)));
1640 host_impl_->ActivateSyncTree();
1641 EXPECT_FALSE(did_request_redraw_);
1642 EXPECT_TRUE(did_request_animate_);
1644 did_request_redraw_ = false;
1645 did_request_animate_ = false;
1646 host_impl_->Animate(start_time);
1647 EXPECT_TRUE(did_request_redraw_);
1648 EXPECT_TRUE(did_request_animate_);
1650 did_request_redraw_ = false;
1651 did_request_animate_ = false;
1652 host_impl_->Animate(halfway_through_animation);
1653 EXPECT_TRUE(did_request_redraw_);
1654 EXPECT_TRUE(did_request_animate_);
1656 did_request_redraw_ = false;
1657 did_request_animate_ = false;
1658 did_request_commit_ = false;
1659 host_impl_->Animate(end_time);
1660 EXPECT_TRUE(did_request_commit_);
1661 EXPECT_FALSE(did_request_animate_);
1663 scoped_ptr<ScrollAndScaleSet> scroll_info =
1664 host_impl_->ProcessScrollDeltas();
1665 EXPECT_EQ(scroll_info->page_scale_delta, 2);
1666 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1667 gfx::Vector2d(-50, -50)));
1670 // Anchor zoom-out
1672 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1673 max_page_scale);
1674 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1676 did_request_redraw_ = false;
1677 did_request_animate_ = false;
1678 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1679 scoped_ptr<PendingPageScaleAnimation> (new PendingPageScaleAnimation(
1680 gfx::Vector2d(25, 25),
1681 true,
1682 min_page_scale,
1683 duration)));
1684 host_impl_->ActivateSyncTree();
1685 EXPECT_FALSE(did_request_redraw_);
1686 EXPECT_TRUE(did_request_animate_);
1688 did_request_redraw_ = false;
1689 did_request_animate_ = false;
1690 host_impl_->Animate(start_time);
1691 EXPECT_TRUE(did_request_redraw_);
1692 EXPECT_TRUE(did_request_animate_);
1694 did_request_redraw_ = false;
1695 did_request_commit_ = false;
1696 did_request_animate_ = false;
1697 host_impl_->Animate(end_time);
1698 EXPECT_TRUE(did_request_redraw_);
1699 EXPECT_FALSE(did_request_animate_);
1700 EXPECT_TRUE(did_request_commit_);
1702 scoped_ptr<ScrollAndScaleSet> scroll_info =
1703 host_impl_->ProcessScrollDeltas();
1704 EXPECT_EQ(scroll_info->page_scale_delta, min_page_scale);
1705 // Pushed to (0,0) via clamping against contents layer size.
1706 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1707 gfx::Vector2d(-50, -50)));
1711 TEST_F(LayerTreeHostImplTest, PageScaleAnimationNoOp) {
1712 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1713 host_impl_->SetViewportSize(gfx::Size(50, 50));
1714 DrawFrame();
1716 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1717 DCHECK(scroll_layer);
1719 float min_page_scale = 0.5f;
1720 float max_page_scale = 4.f;
1721 base::TimeTicks start_time = base::TimeTicks() +
1722 base::TimeDelta::FromSeconds(1);
1723 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1724 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1725 base::TimeTicks end_time = start_time + duration;
1727 // Anchor zoom with unchanged page scale should not change scroll or scale.
1729 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1730 max_page_scale);
1731 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1733 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1734 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1735 gfx::Vector2d(),
1736 true,
1737 1.f,
1738 duration)));
1739 host_impl_->ActivateSyncTree();
1740 host_impl_->Animate(start_time);
1741 host_impl_->Animate(halfway_through_animation);
1742 EXPECT_TRUE(did_request_redraw_);
1743 host_impl_->Animate(end_time);
1744 EXPECT_TRUE(did_request_commit_);
1746 scoped_ptr<ScrollAndScaleSet> scroll_info =
1747 host_impl_->ProcessScrollDeltas();
1748 EXPECT_EQ(scroll_info->page_scale_delta, 1);
1749 ExpectNone(*scroll_info, scroll_layer->id());
1753 TEST_F(LayerTreeHostImplTest, PageScaleAnimationTransferedOnSyncTreeActivate) {
1754 host_impl_->CreatePendingTree();
1755 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
1756 CreateScrollAndContentsLayers(
1757 host_impl_->pending_tree(),
1758 gfx::Size(100, 100));
1759 host_impl_->ActivateSyncTree();
1760 DrawFrame();
1762 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1763 DCHECK(scroll_layer);
1765 float min_page_scale = 0.5f;
1766 float max_page_scale = 4.f;
1767 host_impl_->sync_tree()->PushPageScaleFromMainThread(1.f, min_page_scale,
1768 max_page_scale);
1769 host_impl_->ActivateSyncTree();
1771 base::TimeTicks start_time = base::TimeTicks() +
1772 base::TimeDelta::FromSeconds(1);
1773 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1774 base::TimeTicks third_through_animation = start_time + duration / 3;
1775 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1776 base::TimeTicks end_time = start_time + duration;
1777 float target_scale = 2.f;
1779 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1781 // Make sure TakePageScaleAnimation works properly.
1783 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1784 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1785 gfx::Vector2d(),
1786 false,
1787 target_scale,
1788 duration)));
1789 scoped_ptr<PendingPageScaleAnimation> psa =
1790 host_impl_->sync_tree()->TakePendingPageScaleAnimation();
1791 EXPECT_EQ(target_scale, psa->scale);
1792 EXPECT_EQ(duration, psa->duration);
1793 EXPECT_EQ(nullptr, host_impl_->sync_tree()->TakePendingPageScaleAnimation());
1795 // Recreate the PSA. Nothing should happen here since the tree containing the
1796 // PSA hasn't been activated yet.
1797 did_request_redraw_ = false;
1798 did_request_animate_ = false;
1799 host_impl_->sync_tree()->SetPendingPageScaleAnimation(
1800 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1801 gfx::Vector2d(),
1802 false,
1803 target_scale,
1804 duration)));
1805 host_impl_->Animate(halfway_through_animation);
1806 EXPECT_FALSE(did_request_animate_);
1807 EXPECT_FALSE(did_request_redraw_);
1809 // Activate the sync tree. This should cause the animation to become enabled.
1810 // It should also clear the pointer on the sync tree.
1811 host_impl_->ActivateSyncTree();
1812 EXPECT_EQ(nullptr,
1813 host_impl_->sync_tree()->TakePendingPageScaleAnimation().get());
1814 EXPECT_FALSE(did_request_redraw_);
1815 EXPECT_TRUE(did_request_animate_);
1817 // From here on, make sure the animation runs as normal.
1818 did_request_redraw_ = false;
1819 did_request_animate_ = false;
1820 host_impl_->Animate(start_time);
1821 EXPECT_TRUE(did_request_redraw_);
1822 EXPECT_TRUE(did_request_animate_);
1824 did_request_redraw_ = false;
1825 did_request_animate_ = false;
1826 host_impl_->Animate(third_through_animation);
1827 EXPECT_TRUE(did_request_redraw_);
1828 EXPECT_TRUE(did_request_animate_);
1830 // Another activation shouldn't have any effect on the animation.
1831 host_impl_->ActivateSyncTree();
1833 did_request_redraw_ = false;
1834 did_request_animate_ = false;
1835 host_impl_->Animate(halfway_through_animation);
1836 EXPECT_TRUE(did_request_redraw_);
1837 EXPECT_TRUE(did_request_animate_);
1839 did_request_redraw_ = false;
1840 did_request_animate_ = false;
1841 did_request_commit_ = false;
1842 host_impl_->Animate(end_time);
1843 EXPECT_TRUE(did_request_commit_);
1844 EXPECT_FALSE(did_request_animate_);
1846 scoped_ptr<ScrollAndScaleSet> scroll_info =
1847 host_impl_->ProcessScrollDeltas();
1848 EXPECT_EQ(scroll_info->page_scale_delta, target_scale);
1849 EXPECT_TRUE(ScrollInfoContains(*scroll_info, scroll_layer->id(),
1850 gfx::Vector2d(-50, -50)));
1853 TEST_F(LayerTreeHostImplTest, PageScaleAnimationCompletedNotification) {
1854 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1855 host_impl_->SetViewportSize(gfx::Size(50, 50));
1856 DrawFrame();
1858 LayerImpl* scroll_layer = host_impl_->InnerViewportScrollLayer();
1859 DCHECK(scroll_layer);
1861 base::TimeTicks start_time =
1862 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1863 base::TimeDelta duration = base::TimeDelta::FromMilliseconds(100);
1864 base::TimeTicks halfway_through_animation = start_time + duration / 2;
1865 base::TimeTicks end_time = start_time + duration;
1867 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
1868 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1870 did_complete_page_scale_animation_ = false;
1871 host_impl_->active_tree()->SetPendingPageScaleAnimation(
1872 scoped_ptr<PendingPageScaleAnimation>(new PendingPageScaleAnimation(
1873 gfx::Vector2d(), false, 2.f, duration)));
1874 host_impl_->ActivateSyncTree();
1875 host_impl_->Animate(start_time);
1876 EXPECT_FALSE(did_complete_page_scale_animation_);
1878 host_impl_->Animate(halfway_through_animation);
1879 EXPECT_FALSE(did_complete_page_scale_animation_);
1881 host_impl_->Animate(end_time);
1882 EXPECT_TRUE(did_complete_page_scale_animation_);
1885 class LayerTreeHostImplOverridePhysicalTime : public LayerTreeHostImpl {
1886 public:
1887 LayerTreeHostImplOverridePhysicalTime(
1888 const LayerTreeSettings& settings,
1889 LayerTreeHostImplClient* client,
1890 Proxy* proxy,
1891 SharedBitmapManager* manager,
1892 TaskGraphRunner* task_graph_runner,
1893 RenderingStatsInstrumentation* rendering_stats_instrumentation)
1894 : LayerTreeHostImpl(settings,
1895 client,
1896 proxy,
1897 rendering_stats_instrumentation,
1898 manager,
1899 nullptr,
1900 task_graph_runner,
1901 0) {}
1903 BeginFrameArgs CurrentBeginFrameArgs() const override {
1904 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE,
1905 fake_current_physical_time_);
1908 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now) {
1909 fake_current_physical_time_ = fake_now;
1912 private:
1913 base::TimeTicks fake_current_physical_time_;
1916 class LayerTreeHostImplTestScrollbarAnimation : public LayerTreeHostImplTest {
1917 protected:
1918 void SetupLayers(LayerTreeSettings settings) {
1919 gfx::Size content_size(100, 100);
1921 LayerTreeHostImplOverridePhysicalTime* host_impl_override_time =
1922 new LayerTreeHostImplOverridePhysicalTime(
1923 settings, this, &proxy_, &shared_bitmap_manager_,
1924 &task_graph_runner_, &stats_instrumentation_);
1925 host_impl_ = make_scoped_ptr(host_impl_override_time);
1926 host_impl_->InitializeRenderer(CreateOutputSurface());
1928 SetupScrollAndContentsLayers(content_size);
1929 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
1930 host_impl_->SetViewportSize(
1931 gfx::Size(content_size.width() / 2, content_size.height() / 2));
1933 scoped_ptr<SolidColorScrollbarLayerImpl> scrollbar =
1934 SolidColorScrollbarLayerImpl::Create(host_impl_->active_tree(), 400,
1935 VERTICAL, 10, 0, false, true);
1936 EXPECT_FLOAT_EQ(0.f, scrollbar->opacity());
1938 LayerImpl* scroll = host_impl_->InnerViewportScrollLayer();
1939 LayerImpl* root = scroll->parent()->parent();
1940 scrollbar->SetScrollLayerAndClipLayerByIds(scroll->id(), root->id());
1941 root->AddChild(scrollbar.Pass());
1943 host_impl_->active_tree()->DidBecomeActive();
1944 DrawFrame();
1947 void RunTest(LayerTreeSettings::ScrollbarAnimator animator) {
1948 LayerTreeSettings settings;
1949 settings.scrollbar_animator = animator;
1950 settings.scrollbar_fade_delay_ms = 20;
1951 settings.scrollbar_fade_duration_ms = 20;
1953 SetupLayers(settings);
1955 base::TimeTicks fake_now = base::TimeTicks::Now();
1957 EXPECT_FALSE(did_request_animate_);
1958 EXPECT_FALSE(did_request_redraw_);
1959 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1960 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1962 // If no scroll happened during a scroll gesture, it should have no effect.
1963 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1964 host_impl_->ScrollEnd();
1965 EXPECT_FALSE(did_request_animate_);
1966 EXPECT_FALSE(did_request_redraw_);
1967 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1968 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1970 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1971 // now.
1972 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
1973 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1974 EXPECT_FALSE(did_request_animate_);
1975 EXPECT_TRUE(did_request_redraw_);
1976 did_request_redraw_ = false;
1977 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
1978 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
1980 host_impl_->ScrollEnd();
1981 EXPECT_FALSE(did_request_animate_);
1982 EXPECT_FALSE(did_request_redraw_);
1983 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1984 requested_animation_delay_);
1985 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
1987 fake_now += requested_animation_delay_;
1988 requested_animation_delay_ = base::TimeDelta();
1989 animation_task_.Run();
1990 animation_task_ = base::Closure();
1991 EXPECT_TRUE(did_request_animate_);
1992 did_request_animate_ = false;
1993 EXPECT_FALSE(did_request_redraw_);
1995 // After the scrollbar animation begins, we should start getting redraws.
1996 host_impl_->Animate(fake_now);
1997 EXPECT_TRUE(did_request_animate_);
1998 did_request_animate_ = false;
1999 EXPECT_TRUE(did_request_redraw_);
2000 did_request_redraw_ = false;
2001 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2002 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2004 // Setting the scroll offset outside a scroll should also cause the
2005 // scrollbar to appear and to schedule a scrollbar animation.
2006 host_impl_->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2007 gfx::ScrollOffset(5, 5));
2008 EXPECT_FALSE(did_request_animate_);
2009 EXPECT_FALSE(did_request_redraw_);
2010 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2011 requested_animation_delay_);
2012 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2013 requested_animation_delay_ = base::TimeDelta();
2014 animation_task_ = base::Closure();
2016 // Scrollbar animation is not triggered unnecessarily.
2017 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL);
2018 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2019 EXPECT_FALSE(did_request_animate_);
2020 EXPECT_TRUE(did_request_redraw_);
2021 did_request_redraw_ = false;
2022 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2023 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2025 host_impl_->ScrollEnd();
2026 EXPECT_FALSE(did_request_animate_);
2027 EXPECT_FALSE(did_request_redraw_);
2028 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_);
2029 EXPECT_TRUE(animation_task_.Equals(base::Closure()));
2031 // Changing page scale triggers scrollbar animation.
2032 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 4.f);
2033 host_impl_->SetPageScaleOnActiveTree(1.1f);
2034 EXPECT_FALSE(did_request_animate_);
2035 EXPECT_FALSE(did_request_redraw_);
2036 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2037 requested_animation_delay_);
2038 EXPECT_FALSE(animation_task_.Equals(base::Closure()));
2039 requested_animation_delay_ = base::TimeDelta();
2040 animation_task_ = base::Closure();
2044 TEST_F(LayerTreeHostImplTestScrollbarAnimation, LinearFade) {
2045 RunTest(LayerTreeSettings::LINEAR_FADE);
2048 TEST_F(LayerTreeHostImplTestScrollbarAnimation, Thinning) {
2049 RunTest(LayerTreeSettings::THINNING);
2052 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2053 float device_scale_factor) {
2054 LayerTreeSettings settings;
2055 settings.scrollbar_fade_delay_ms = 500;
2056 settings.scrollbar_fade_duration_ms = 300;
2057 settings.scrollbar_animator = LayerTreeSettings::THINNING;
2059 gfx::Size viewport_size(300, 200);
2060 gfx::Size device_viewport_size = gfx::ToFlooredSize(
2061 gfx::ScaleSize(viewport_size, device_scale_factor));
2062 gfx::Size content_size(1000, 1000);
2064 CreateHostImpl(settings, CreateOutputSurface());
2065 host_impl_->SetDeviceScaleFactor(device_scale_factor);
2066 host_impl_->SetViewportSize(device_viewport_size);
2068 scoped_ptr<LayerImpl> root =
2069 LayerImpl::Create(host_impl_->active_tree(), 1);
2070 root->SetBounds(viewport_size);
2071 root->SetHasRenderSurface(true);
2073 scoped_ptr<LayerImpl> scroll =
2074 LayerImpl::Create(host_impl_->active_tree(), 2);
2075 scroll->SetScrollClipLayer(root->id());
2076 scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2077 scroll->SetBounds(content_size);
2078 scroll->SetIsContainerForFixedPositionLayers(true);
2080 scoped_ptr<LayerImpl> contents =
2081 LayerImpl::Create(host_impl_->active_tree(), 3);
2082 contents->SetDrawsContent(true);
2083 contents->SetBounds(content_size);
2085 // The scrollbar is on the right side.
2086 scoped_ptr<PaintedScrollbarLayerImpl> scrollbar =
2087 PaintedScrollbarLayerImpl::Create(host_impl_->active_tree(), 5, VERTICAL);
2088 scrollbar->SetDrawsContent(true);
2089 scrollbar->SetBounds(gfx::Size(15, viewport_size.height()));
2090 scrollbar->SetPosition(gfx::Point(285, 0));
2092 scroll->AddChild(contents.Pass());
2093 root->AddChild(scroll.Pass());
2094 scrollbar->SetScrollLayerAndClipLayerByIds(2, 1);
2095 root->AddChild(scrollbar.Pass());
2097 host_impl_->active_tree()->SetRootLayer(root.Pass());
2098 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
2099 Layer::INVALID_ID);
2100 host_impl_->active_tree()->DidBecomeActive();
2101 DrawFrame();
2103 LayerImpl* root_scroll =
2104 host_impl_->active_tree()->InnerViewportScrollLayer();
2105 ASSERT_TRUE(root_scroll->scrollbar_animation_controller());
2106 ScrollbarAnimationControllerThinning* scrollbar_animation_controller =
2107 static_cast<ScrollbarAnimationControllerThinning*>(
2108 root_scroll->scrollbar_animation_controller());
2109 scrollbar_animation_controller->set_mouse_move_distance_for_test(100.f);
2111 host_impl_->MouseMoveAt(gfx::Point(1, 1));
2112 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2114 host_impl_->MouseMoveAt(gfx::Point(200, 50));
2115 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2117 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2118 EXPECT_FALSE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2120 scrollbar_animation_controller->set_mouse_move_distance_for_test(102.f);
2121 host_impl_->MouseMoveAt(gfx::Point(184, 100));
2122 EXPECT_TRUE(scrollbar_animation_controller->mouse_is_near_scrollbar());
2124 did_request_redraw_ = false;
2125 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2126 host_impl_->MouseMoveAt(gfx::Point(290, 100));
2127 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2128 host_impl_->MouseMoveAt(gfx::Point(290, 120));
2129 EXPECT_EQ(2, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2130 host_impl_->MouseMoveAt(gfx::Point(150, 120));
2131 EXPECT_EQ(0, host_impl_->scroll_layer_id_when_mouse_over_scrollbar());
2134 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf1) {
2135 SetupMouseMoveAtWithDeviceScale(1.f);
2138 TEST_F(LayerTreeHostImplTest, MouseMoveAtWithDeviceScaleOf2) {
2139 SetupMouseMoveAtWithDeviceScale(2.f);
2142 TEST_F(LayerTreeHostImplTest, CompositorFrameMetadata) {
2143 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2144 host_impl_->SetViewportSize(gfx::Size(50, 50));
2145 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
2146 DrawFrame();
2148 CompositorFrameMetadata metadata =
2149 host_impl_->MakeCompositorFrameMetadata();
2150 EXPECT_EQ(gfx::Vector2dF(), metadata.root_scroll_offset);
2151 EXPECT_EQ(1.f, metadata.page_scale_factor);
2152 EXPECT_EQ(gfx::SizeF(50.f, 50.f), metadata.scrollable_viewport_size);
2153 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2154 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2155 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2156 EXPECT_FALSE(metadata.root_overflow_x_hidden);
2157 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2160 // Scrolling should update metadata immediately.
2161 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2162 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2163 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2165 CompositorFrameMetadata metadata =
2166 host_impl_->MakeCompositorFrameMetadata();
2167 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2169 host_impl_->ScrollEnd();
2171 CompositorFrameMetadata metadata =
2172 host_impl_->MakeCompositorFrameMetadata();
2173 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2176 // Root "overflow: hidden" properties should be reflected on the outer
2177 // viewport scroll layer.
2179 host_impl_->active_tree()
2180 ->OuterViewportScrollLayer()
2181 ->set_user_scrollable_horizontal(false);
2182 CompositorFrameMetadata metadata =
2183 host_impl_->MakeCompositorFrameMetadata();
2184 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2185 EXPECT_FALSE(metadata.root_overflow_y_hidden);
2187 host_impl_->active_tree()
2188 ->OuterViewportScrollLayer()
2189 ->set_user_scrollable_vertical(false);
2190 metadata = host_impl_->MakeCompositorFrameMetadata();
2191 EXPECT_TRUE(metadata.root_overflow_x_hidden);
2192 EXPECT_TRUE(metadata.root_overflow_y_hidden);
2195 // Page scale should update metadata correctly (shrinking only the viewport).
2196 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
2197 host_impl_->PinchGestureBegin();
2198 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
2199 host_impl_->PinchGestureEnd();
2200 host_impl_->ScrollEnd();
2202 CompositorFrameMetadata metadata =
2203 host_impl_->MakeCompositorFrameMetadata();
2204 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2205 EXPECT_EQ(2.f, metadata.page_scale_factor);
2206 EXPECT_EQ(gfx::SizeF(25.f, 25.f), metadata.scrollable_viewport_size);
2207 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2208 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2209 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2212 // Likewise if set from the main thread.
2213 host_impl_->ProcessScrollDeltas();
2214 host_impl_->active_tree()->PushPageScaleFromMainThread(4.f, 0.5f, 4.f);
2215 host_impl_->SetPageScaleOnActiveTree(4.f);
2217 CompositorFrameMetadata metadata =
2218 host_impl_->MakeCompositorFrameMetadata();
2219 EXPECT_EQ(gfx::Vector2dF(0.f, 10.f), metadata.root_scroll_offset);
2220 EXPECT_EQ(4.f, metadata.page_scale_factor);
2221 EXPECT_EQ(gfx::SizeF(12.5f, 12.5f), metadata.scrollable_viewport_size);
2222 EXPECT_EQ(gfx::SizeF(100.f, 100.f), metadata.root_layer_size);
2223 EXPECT_EQ(0.5f, metadata.min_page_scale_factor);
2224 EXPECT_EQ(4.f, metadata.max_page_scale_factor);
2228 class DidDrawCheckLayer : public LayerImpl {
2229 public:
2230 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
2231 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl, id));
2234 bool WillDraw(DrawMode draw_mode, ResourceProvider* provider) override {
2235 will_draw_called_ = true;
2236 if (will_draw_returns_false_)
2237 return false;
2238 return LayerImpl::WillDraw(draw_mode, provider);
2241 void AppendQuads(RenderPass* render_pass,
2242 AppendQuadsData* append_quads_data) override {
2243 append_quads_called_ = true;
2244 LayerImpl::AppendQuads(render_pass, append_quads_data);
2247 void DidDraw(ResourceProvider* provider) override {
2248 did_draw_called_ = true;
2249 LayerImpl::DidDraw(provider);
2252 bool will_draw_called() const { return will_draw_called_; }
2253 bool append_quads_called() const { return append_quads_called_; }
2254 bool did_draw_called() const { return did_draw_called_; }
2256 void set_will_draw_returns_false() { will_draw_returns_false_ = true; }
2258 void ClearDidDrawCheck() {
2259 will_draw_called_ = false;
2260 append_quads_called_ = false;
2261 did_draw_called_ = false;
2264 static void IgnoreResult(scoped_ptr<CopyOutputResult> result) {}
2266 void AddCopyRequest() {
2267 ScopedPtrVector<CopyOutputRequest> requests;
2268 requests.push_back(
2269 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult)));
2270 SetHasRenderSurface(true);
2271 PassCopyRequests(&requests);
2274 protected:
2275 DidDrawCheckLayer(LayerTreeImpl* tree_impl, int id)
2276 : LayerImpl(tree_impl, id),
2277 will_draw_returns_false_(false),
2278 will_draw_called_(false),
2279 append_quads_called_(false),
2280 did_draw_called_(false) {
2281 SetBounds(gfx::Size(10, 10));
2282 SetDrawsContent(true);
2283 draw_properties().visible_layer_rect = gfx::Rect(0, 0, 10, 10);
2286 private:
2287 bool will_draw_returns_false_;
2288 bool will_draw_called_;
2289 bool append_quads_called_;
2290 bool did_draw_called_;
2293 TEST_F(LayerTreeHostImplTest, WillDrawReturningFalseDoesNotCall) {
2294 // The root layer is always drawn, so run this test on a child layer that
2295 // will be masked out by the root layer's bounds.
2296 host_impl_->active_tree()->SetRootLayer(
2297 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2298 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2299 host_impl_->active_tree()->root_layer());
2301 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2302 root->SetHasRenderSurface(true);
2303 DidDrawCheckLayer* layer =
2304 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2307 LayerTreeHostImpl::FrameData frame;
2308 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2309 host_impl_->DrawLayers(&frame);
2310 host_impl_->DidDrawAllLayers(frame);
2312 EXPECT_TRUE(layer->will_draw_called());
2313 EXPECT_TRUE(layer->append_quads_called());
2314 EXPECT_TRUE(layer->did_draw_called());
2317 host_impl_->SetViewportDamage(gfx::Rect(10, 10));
2320 LayerTreeHostImpl::FrameData frame;
2322 layer->set_will_draw_returns_false();
2323 layer->ClearDidDrawCheck();
2325 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2326 host_impl_->DrawLayers(&frame);
2327 host_impl_->DidDrawAllLayers(frame);
2329 EXPECT_TRUE(layer->will_draw_called());
2330 EXPECT_FALSE(layer->append_quads_called());
2331 EXPECT_FALSE(layer->did_draw_called());
2335 TEST_F(LayerTreeHostImplTest, DidDrawNotCalledOnHiddenLayer) {
2336 // The root layer is always drawn, so run this test on a child layer that
2337 // will be masked out by the root layer's bounds.
2338 host_impl_->active_tree()->SetRootLayer(
2339 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2340 DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(
2341 host_impl_->active_tree()->root_layer());
2342 root->SetMasksToBounds(true);
2343 root->SetHasRenderSurface(true);
2344 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2345 DidDrawCheckLayer* layer =
2346 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2347 // Ensure visible_layer_rect for layer is empty.
2348 layer->SetPosition(gfx::PointF(100.f, 100.f));
2349 layer->SetBounds(gfx::Size(10, 10));
2351 LayerTreeHostImpl::FrameData frame;
2353 EXPECT_FALSE(layer->will_draw_called());
2354 EXPECT_FALSE(layer->did_draw_called());
2356 host_impl_->active_tree()->BuildPropertyTreesForTesting();
2357 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2358 host_impl_->DrawLayers(&frame);
2359 host_impl_->DidDrawAllLayers(frame);
2361 EXPECT_FALSE(layer->will_draw_called());
2362 EXPECT_FALSE(layer->did_draw_called());
2364 EXPECT_TRUE(layer->visible_layer_rect().IsEmpty());
2366 // Ensure visible_layer_rect for layer is not empty
2367 layer->SetPosition(gfx::PointF());
2369 EXPECT_FALSE(layer->will_draw_called());
2370 EXPECT_FALSE(layer->did_draw_called());
2372 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2373 host_impl_->DrawLayers(&frame);
2374 host_impl_->DidDrawAllLayers(frame);
2376 EXPECT_TRUE(layer->will_draw_called());
2377 EXPECT_TRUE(layer->did_draw_called());
2379 EXPECT_FALSE(layer->visible_layer_rect().IsEmpty());
2382 TEST_F(LayerTreeHostImplTest, WillDrawNotCalledOnOccludedLayer) {
2383 gfx::Size big_size(1000, 1000);
2384 host_impl_->SetViewportSize(big_size);
2386 host_impl_->active_tree()->SetRootLayer(
2387 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2388 DidDrawCheckLayer* root =
2389 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2391 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2392 DidDrawCheckLayer* occluded_layer =
2393 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2395 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2396 root->SetHasRenderSurface(true);
2397 DidDrawCheckLayer* top_layer =
2398 static_cast<DidDrawCheckLayer*>(root->children()[1]);
2399 // This layer covers the occluded_layer above. Make this layer large so it can
2400 // occlude.
2401 top_layer->SetBounds(big_size);
2402 top_layer->SetContentsOpaque(true);
2404 LayerTreeHostImpl::FrameData frame;
2406 EXPECT_FALSE(occluded_layer->will_draw_called());
2407 EXPECT_FALSE(occluded_layer->did_draw_called());
2408 EXPECT_FALSE(top_layer->will_draw_called());
2409 EXPECT_FALSE(top_layer->did_draw_called());
2411 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2412 host_impl_->DrawLayers(&frame);
2413 host_impl_->DidDrawAllLayers(frame);
2415 EXPECT_FALSE(occluded_layer->will_draw_called());
2416 EXPECT_FALSE(occluded_layer->did_draw_called());
2417 EXPECT_TRUE(top_layer->will_draw_called());
2418 EXPECT_TRUE(top_layer->did_draw_called());
2421 TEST_F(LayerTreeHostImplTest, DidDrawCalledOnAllLayers) {
2422 host_impl_->active_tree()->SetRootLayer(
2423 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2424 DidDrawCheckLayer* root =
2425 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2427 root->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 2));
2428 root->SetHasRenderSurface(true);
2429 DidDrawCheckLayer* layer1 =
2430 static_cast<DidDrawCheckLayer*>(root->children()[0]);
2432 layer1->AddChild(DidDrawCheckLayer::Create(host_impl_->active_tree(), 3));
2433 DidDrawCheckLayer* layer2 =
2434 static_cast<DidDrawCheckLayer*>(layer1->children()[0]);
2436 layer1->SetHasRenderSurface(true);
2437 layer1->SetShouldFlattenTransform(true);
2439 EXPECT_FALSE(root->did_draw_called());
2440 EXPECT_FALSE(layer1->did_draw_called());
2441 EXPECT_FALSE(layer2->did_draw_called());
2443 LayerTreeHostImpl::FrameData frame;
2444 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2445 host_impl_->active_tree()->root_layer());
2446 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2447 host_impl_->DrawLayers(&frame);
2448 host_impl_->DidDrawAllLayers(frame);
2450 EXPECT_TRUE(root->did_draw_called());
2451 EXPECT_TRUE(layer1->did_draw_called());
2452 EXPECT_TRUE(layer2->did_draw_called());
2454 EXPECT_NE(root->render_surface(), layer1->render_surface());
2455 EXPECT_TRUE(layer1->render_surface());
2458 class MissingTextureAnimatingLayer : public DidDrawCheckLayer {
2459 public:
2460 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
2461 int id,
2462 bool tile_missing,
2463 bool had_incomplete_tile,
2464 bool animating,
2465 ResourceProvider* resource_provider) {
2466 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl,
2468 tile_missing,
2469 had_incomplete_tile,
2470 animating,
2471 resource_provider));
2474 void AppendQuads(RenderPass* render_pass,
2475 AppendQuadsData* append_quads_data) override {
2476 LayerImpl::AppendQuads(render_pass, append_quads_data);
2477 if (had_incomplete_tile_)
2478 append_quads_data->num_incomplete_tiles++;
2479 if (tile_missing_)
2480 append_quads_data->num_missing_tiles++;
2483 private:
2484 MissingTextureAnimatingLayer(LayerTreeImpl* tree_impl,
2485 int id,
2486 bool tile_missing,
2487 bool had_incomplete_tile,
2488 bool animating,
2489 ResourceProvider* resource_provider)
2490 : DidDrawCheckLayer(tree_impl, id),
2491 tile_missing_(tile_missing),
2492 had_incomplete_tile_(had_incomplete_tile) {
2493 if (animating)
2494 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2497 bool tile_missing_;
2498 bool had_incomplete_tile_;
2501 struct PrepareToDrawSuccessTestCase {
2502 struct State {
2503 bool has_missing_tile = false;
2504 bool has_incomplete_tile = false;
2505 bool is_animating = false;
2506 bool has_copy_request = false;
2508 bool high_res_required = false;
2509 State layer_before;
2510 State layer_between;
2511 State layer_after;
2512 DrawResult expected_result;
2514 explicit PrepareToDrawSuccessTestCase(DrawResult result)
2515 : expected_result(result) {}
2518 TEST_F(LayerTreeHostImplTest, PrepareToDrawSucceedsAndFails) {
2519 std::vector<PrepareToDrawSuccessTestCase> cases;
2521 // 0. Default case.
2522 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2523 // 1. Animated layer first.
2524 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2525 cases.back().layer_before.is_animating = true;
2526 // 2. Animated layer between.
2527 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2528 cases.back().layer_between.is_animating = true;
2529 // 3. Animated layer last.
2530 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2531 cases.back().layer_after.is_animating = true;
2532 // 4. Missing tile first.
2533 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2534 cases.back().layer_before.has_missing_tile = true;
2535 // 5. Missing tile between.
2536 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2537 cases.back().layer_between.has_missing_tile = true;
2538 // 6. Missing tile last.
2539 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2540 cases.back().layer_after.has_missing_tile = true;
2541 // 7. Incomplete tile first.
2542 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2543 cases.back().layer_before.has_incomplete_tile = true;
2544 // 8. Incomplete tile between.
2545 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2546 cases.back().layer_between.has_incomplete_tile = true;
2547 // 9. Incomplete tile last.
2548 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2549 cases.back().layer_after.has_incomplete_tile = true;
2550 // 10. Animation with missing tile.
2551 cases.push_back(
2552 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS));
2553 cases.back().layer_between.has_missing_tile = true;
2554 cases.back().layer_between.is_animating = true;
2555 // 11. Animation with incomplete tile.
2556 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2557 cases.back().layer_between.has_incomplete_tile = true;
2558 cases.back().layer_between.is_animating = true;
2560 // 12. High res required.
2561 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2562 cases.back().high_res_required = true;
2563 // 13. High res required with incomplete tile.
2564 cases.push_back(
2565 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2566 cases.back().high_res_required = true;
2567 cases.back().layer_between.has_incomplete_tile = true;
2568 // 14. High res required with missing tile.
2569 cases.push_back(
2570 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2571 cases.back().high_res_required = true;
2572 cases.back().layer_between.has_missing_tile = true;
2574 // 15. High res required is higher priority than animating missing tiles.
2575 cases.push_back(
2576 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2577 cases.back().high_res_required = true;
2578 cases.back().layer_between.has_missing_tile = true;
2579 cases.back().layer_after.has_missing_tile = true;
2580 cases.back().layer_after.is_animating = true;
2581 // 16. High res required is higher priority than animating missing tiles.
2582 cases.push_back(
2583 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT));
2584 cases.back().high_res_required = true;
2585 cases.back().layer_between.has_missing_tile = true;
2586 cases.back().layer_before.has_missing_tile = true;
2587 cases.back().layer_before.is_animating = true;
2589 host_impl_->active_tree()->SetRootLayer(
2590 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2591 DidDrawCheckLayer* root =
2592 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2593 root->SetHasRenderSurface(true);
2595 LayerTreeHostImpl::FrameData frame;
2596 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2597 host_impl_->DrawLayers(&frame);
2598 host_impl_->DidDrawAllLayers(frame);
2599 host_impl_->SwapBuffers(frame);
2601 for (size_t i = 0; i < cases.size(); ++i) {
2602 const auto& testcase = cases[i];
2603 std::vector<LayerImpl*> to_remove;
2604 for (auto* child : root->children())
2605 to_remove.push_back(child);
2606 for (auto* child : to_remove)
2607 root->RemoveChild(child);
2609 std::ostringstream scope;
2610 scope << "Test case: " << i;
2611 SCOPED_TRACE(scope.str());
2613 root->AddChild(MissingTextureAnimatingLayer::Create(
2614 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2615 testcase.layer_before.has_incomplete_tile,
2616 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2617 DidDrawCheckLayer* before =
2618 static_cast<DidDrawCheckLayer*>(root->children().back());
2619 if (testcase.layer_before.has_copy_request)
2620 before->AddCopyRequest();
2622 root->AddChild(MissingTextureAnimatingLayer::Create(
2623 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2624 testcase.layer_between.has_incomplete_tile,
2625 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2626 DidDrawCheckLayer* between =
2627 static_cast<DidDrawCheckLayer*>(root->children().back());
2628 if (testcase.layer_between.has_copy_request)
2629 between->AddCopyRequest();
2631 root->AddChild(MissingTextureAnimatingLayer::Create(
2632 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2633 testcase.layer_after.has_incomplete_tile,
2634 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2635 DidDrawCheckLayer* after =
2636 static_cast<DidDrawCheckLayer*>(root->children().back());
2637 if (testcase.layer_after.has_copy_request)
2638 after->AddCopyRequest();
2640 if (testcase.high_res_required)
2641 host_impl_->SetRequiresHighResToDraw();
2643 LayerTreeHostImpl::FrameData frame;
2644 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2645 host_impl_->DrawLayers(&frame);
2646 host_impl_->DidDrawAllLayers(frame);
2647 host_impl_->SwapBuffers(frame);
2651 TEST_F(LayerTreeHostImplTest,
2652 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame) {
2653 CreateHostImpl(DefaultSettings(),
2654 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2655 EXPECT_TRUE(host_impl_->output_surface()
2656 ->capabilities()
2657 .draw_and_swap_full_viewport_every_frame);
2659 std::vector<PrepareToDrawSuccessTestCase> cases;
2661 // 0. Default case.
2662 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2663 // 1. Animation with missing tile.
2664 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2665 cases.back().layer_between.has_missing_tile = true;
2666 cases.back().layer_between.is_animating = true;
2667 // 2. High res required with incomplete tile.
2668 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2669 cases.back().high_res_required = true;
2670 cases.back().layer_between.has_incomplete_tile = true;
2671 // 3. High res required with missing tile.
2672 cases.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS));
2673 cases.back().high_res_required = true;
2674 cases.back().layer_between.has_missing_tile = true;
2676 host_impl_->active_tree()->SetRootLayer(
2677 DidDrawCheckLayer::Create(host_impl_->active_tree(), 1));
2678 DidDrawCheckLayer* root =
2679 static_cast<DidDrawCheckLayer*>(host_impl_->active_tree()->root_layer());
2680 root->SetHasRenderSurface(true);
2682 LayerTreeHostImpl::FrameData frame;
2683 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
2684 host_impl_->DrawLayers(&frame);
2685 host_impl_->DidDrawAllLayers(frame);
2686 host_impl_->SwapBuffers(frame);
2688 for (size_t i = 0; i < cases.size(); ++i) {
2689 const auto& testcase = cases[i];
2690 std::vector<LayerImpl*> to_remove;
2691 for (auto* child : root->children())
2692 to_remove.push_back(child);
2693 for (auto* child : to_remove)
2694 root->RemoveChild(child);
2696 std::ostringstream scope;
2697 scope << "Test case: " << i;
2698 SCOPED_TRACE(scope.str());
2700 root->AddChild(MissingTextureAnimatingLayer::Create(
2701 host_impl_->active_tree(), 2, testcase.layer_before.has_missing_tile,
2702 testcase.layer_before.has_incomplete_tile,
2703 testcase.layer_before.is_animating, host_impl_->resource_provider()));
2704 DidDrawCheckLayer* before =
2705 static_cast<DidDrawCheckLayer*>(root->children().back());
2706 if (testcase.layer_before.has_copy_request)
2707 before->AddCopyRequest();
2709 root->AddChild(MissingTextureAnimatingLayer::Create(
2710 host_impl_->active_tree(), 3, testcase.layer_between.has_missing_tile,
2711 testcase.layer_between.has_incomplete_tile,
2712 testcase.layer_between.is_animating, host_impl_->resource_provider()));
2713 DidDrawCheckLayer* between =
2714 static_cast<DidDrawCheckLayer*>(root->children().back());
2715 if (testcase.layer_between.has_copy_request)
2716 between->AddCopyRequest();
2718 root->AddChild(MissingTextureAnimatingLayer::Create(
2719 host_impl_->active_tree(), 4, testcase.layer_after.has_missing_tile,
2720 testcase.layer_after.has_incomplete_tile,
2721 testcase.layer_after.is_animating, host_impl_->resource_provider()));
2722 DidDrawCheckLayer* after =
2723 static_cast<DidDrawCheckLayer*>(root->children().back());
2724 if (testcase.layer_after.has_copy_request)
2725 after->AddCopyRequest();
2727 if (testcase.high_res_required)
2728 host_impl_->SetRequiresHighResToDraw();
2730 LayerTreeHostImpl::FrameData frame;
2731 EXPECT_EQ(testcase.expected_result, host_impl_->PrepareToDraw(&frame));
2732 host_impl_->DrawLayers(&frame);
2733 host_impl_->DidDrawAllLayers(frame);
2734 host_impl_->SwapBuffers(frame);
2738 TEST_F(LayerTreeHostImplTest, ScrollRootIgnored) {
2739 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
2740 root->SetScrollClipLayer(Layer::INVALID_ID);
2741 root->SetHasRenderSurface(true);
2742 host_impl_->active_tree()->SetRootLayer(root.Pass());
2743 DrawFrame();
2745 // Scroll event is ignored because layer is not scrollable.
2746 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
2747 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
2748 EXPECT_FALSE(did_request_redraw_);
2749 EXPECT_FALSE(did_request_commit_);
2752 TEST_F(LayerTreeHostImplTest, ClampingAfterActivation) {
2753 host_impl_->CreatePendingTree();
2754 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
2755 CreateScrollAndContentsLayers(host_impl_->pending_tree(),
2756 gfx::Size(100, 100));
2757 host_impl_->ActivateSyncTree();
2759 host_impl_->CreatePendingTree();
2760 const gfx::ScrollOffset pending_scroll = gfx::ScrollOffset(-100, -100);
2761 LayerImpl* active_outer_layer =
2762 host_impl_->active_tree()->OuterViewportScrollLayer();
2763 LayerImpl* pending_outer_layer =
2764 host_impl_->pending_tree()->OuterViewportScrollLayer();
2765 pending_outer_layer->PushScrollOffsetFromMainThread(pending_scroll);
2767 host_impl_->ActivateSyncTree();
2768 // Scrolloffsets on the active tree will be clamped after activation.
2769 EXPECT_EQ(active_outer_layer->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
2772 class LayerTreeHostImplTopControlsTest : public LayerTreeHostImplTest {
2773 public:
2774 LayerTreeHostImplTopControlsTest()
2775 // Make the clip size the same as the layer (content) size so the layer is
2776 // non-scrollable.
2777 : layer_size_(10, 10),
2778 clip_size_(layer_size_),
2779 top_controls_height_(50) {
2780 viewport_size_ = gfx::Size(clip_size_.width(),
2781 clip_size_.height() + top_controls_height_);
2784 bool CreateHostImpl(const LayerTreeSettings& settings,
2785 scoped_ptr<OutputSurface> output_surface) override {
2786 bool init =
2787 LayerTreeHostImplTest::CreateHostImpl(settings, output_surface.Pass());
2788 if (init) {
2789 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
2790 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
2791 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
2793 return init;
2796 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2797 const gfx::Size& inner_viewport_size,
2798 const gfx::Size& outer_viewport_size,
2799 const gfx::Size& scroll_layer_size) {
2800 CreateHostImpl(settings_, CreateOutputSurface());
2801 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
2802 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
2803 host_impl_->DidChangeTopControlsPosition();
2805 scoped_ptr<LayerImpl> root =
2806 LayerImpl::Create(host_impl_->active_tree(), 1);
2807 scoped_ptr<LayerImpl> root_clip =
2808 LayerImpl::Create(host_impl_->active_tree(), 2);
2809 scoped_ptr<LayerImpl> page_scale =
2810 LayerImpl::Create(host_impl_->active_tree(), 3);
2812 scoped_ptr<LayerImpl> outer_scroll =
2813 LayerImpl::Create(host_impl_->active_tree(), 4);
2814 scoped_ptr<LayerImpl> outer_clip =
2815 LayerImpl::Create(host_impl_->active_tree(), 5);
2817 root_clip->SetBounds(inner_viewport_size);
2818 root->SetScrollClipLayer(root_clip->id());
2819 root->SetBounds(outer_viewport_size);
2820 root->SetPosition(gfx::PointF());
2821 root->SetDrawsContent(false);
2822 root->SetIsContainerForFixedPositionLayers(true);
2823 root_clip->SetHasRenderSurface(true);
2824 outer_clip->SetBounds(outer_viewport_size);
2825 outer_scroll->SetScrollClipLayer(outer_clip->id());
2826 outer_scroll->SetBounds(scroll_layer_size);
2827 outer_scroll->SetPosition(gfx::PointF());
2828 outer_scroll->SetDrawsContent(false);
2829 outer_scroll->SetIsContainerForFixedPositionLayers(true);
2831 int inner_viewport_scroll_layer_id = root->id();
2832 int outer_viewport_scroll_layer_id = outer_scroll->id();
2833 int page_scale_layer_id = page_scale->id();
2835 outer_clip->AddChild(outer_scroll.Pass());
2836 root->AddChild(outer_clip.Pass());
2837 page_scale->AddChild(root.Pass());
2838 root_clip->AddChild(page_scale.Pass());
2840 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
2841 host_impl_->active_tree()->SetViewportLayersFromIds(
2842 Layer::INVALID_ID, page_scale_layer_id, inner_viewport_scroll_layer_id,
2843 outer_viewport_scroll_layer_id);
2845 host_impl_->SetViewportSize(inner_viewport_size);
2846 LayerImpl* root_clip_ptr = host_impl_->active_tree()->root_layer();
2847 EXPECT_EQ(inner_viewport_size, root_clip_ptr->bounds());
2850 protected:
2851 gfx::Size layer_size_;
2852 gfx::Size clip_size_;
2853 gfx::Size viewport_size_;
2854 float top_controls_height_;
2856 LayerTreeSettings settings_;
2857 }; // class LayerTreeHostImplTopControlsTest
2859 TEST_F(LayerTreeHostImplTopControlsTest, ScrollTopControlsByFractionalAmount) {
2860 SetupTopControlsAndScrollLayerWithVirtualViewport(
2861 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2862 DrawFrame();
2864 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2865 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2867 // Make the test scroll delta a fractional amount, to verify that the
2868 // fixed container size delta is (1) non-zero, and (2) fractional, and
2869 // (3) matches the movement of the top controls.
2870 gfx::Vector2dF top_controls_scroll_delta(0.f, 5.25f);
2871 host_impl_->top_controls_manager()->ScrollBegin();
2872 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2873 host_impl_->top_controls_manager()->ScrollEnd();
2875 LayerImpl* inner_viewport_scroll_layer =
2876 host_impl_->active_tree()->InnerViewportScrollLayer();
2877 DCHECK(inner_viewport_scroll_layer);
2878 host_impl_->ScrollEnd();
2879 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
2880 inner_viewport_scroll_layer->FixedContainerSizeDelta().y());
2883 // In this test, the outer viewport is initially unscrollable. We test that a
2884 // scroll initiated on the inner viewport, causing the top controls to show and
2885 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2886 TEST_F(LayerTreeHostImplTopControlsTest,
2887 TopControlsOuterViewportBecomesScrollable) {
2888 SetupTopControlsAndScrollLayerWithVirtualViewport(
2889 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2890 DrawFrame();
2892 LayerImpl* inner_scroll =
2893 host_impl_->active_tree()->InnerViewportScrollLayer();
2894 LayerImpl* inner_container =
2895 host_impl_->active_tree()->InnerViewportContainerLayer();
2896 LayerImpl* outer_scroll =
2897 host_impl_->active_tree()->OuterViewportScrollLayer();
2898 LayerImpl* outer_container =
2899 host_impl_->active_tree()->OuterViewportContainerLayer();
2901 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2902 outer_scroll->SetDrawsContent(true);
2903 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 1.f, 2.f);
2905 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2906 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2907 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 50.f));
2909 // The entire scroll delta should have been used to hide the top controls.
2910 // The viewport layers should be resized back to their full sizes.
2911 EXPECT_EQ(0.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2912 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2913 EXPECT_EQ(100.f, inner_container->BoundsForScrolling().height());
2914 EXPECT_EQ(100.f, outer_container->BoundsForScrolling().height());
2916 // The inner viewport should be scrollable by 50px * page_scale.
2917 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, 100.f));
2918 EXPECT_EQ(50.f, inner_scroll->CurrentScrollOffset().y());
2919 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2920 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll->MaxScrollOffset());
2922 host_impl_->ScrollEnd();
2924 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2925 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2926 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
2928 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2930 // The entire scroll delta should have been used to show the top controls.
2931 // The outer viewport should be resized to accomodate and scrolled to the
2932 // bottom of the document to keep the viewport in place.
2933 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
2934 EXPECT_EQ(50.f, outer_container->BoundsForScrolling().height());
2935 EXPECT_EQ(50.f, inner_container->BoundsForScrolling().height());
2936 EXPECT_EQ(25.f, outer_scroll->CurrentScrollOffset().y());
2937 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2939 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2940 // since it wasn't scrollable when the scroll began.
2941 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -20.f));
2942 EXPECT_EQ(15.f, outer_scroll->CurrentScrollOffset().y());
2943 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2945 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -30.f));
2946 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2947 EXPECT_EQ(25.f, inner_scroll->CurrentScrollOffset().y());
2949 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f, -50.f));
2950 host_impl_->ScrollEnd();
2952 EXPECT_EQ(0.f, outer_scroll->CurrentScrollOffset().y());
2953 EXPECT_EQ(0.f, inner_scroll->CurrentScrollOffset().y());
2956 // Test that the fixed position container delta is appropriately adjusted
2957 // by the top controls showing/hiding and page scale doesn't affect it.
2958 TEST_F(LayerTreeHostImplTopControlsTest, FixedContainerDelta) {
2959 SetupTopControlsAndScrollLayerWithVirtualViewport(
2960 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2961 DrawFrame();
2962 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
2964 float page_scale = 1.5f;
2965 LayerImpl* outer_viewport_scroll_layer =
2966 host_impl_->active_tree()->OuterViewportScrollLayer();
2968 // Zoom in, since the fixed container is the outer viewport, the delta should
2969 // not be scaled.
2970 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
2972 EXPECT_EQ(InputHandler::SCROLL_STARTED,
2973 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
2975 // Scroll down, the top controls hiding should expand the viewport size so
2976 // the delta should be equal to the scroll distance.
2977 gfx::Vector2dF top_controls_scroll_delta(0.f, 20.f);
2978 host_impl_->top_controls_manager()->ScrollBegin();
2979 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2980 EXPECT_FLOAT_EQ(top_controls_height_ - top_controls_scroll_delta.y(),
2981 host_impl_->top_controls_manager()->ContentTopOffset());
2982 EXPECT_FLOAT_EQ(top_controls_scroll_delta.y(),
2983 outer_viewport_scroll_layer->FixedContainerSizeDelta().y());
2984 host_impl_->ScrollEnd();
2986 // Scroll past the maximum extent. The delta shouldn't be greater than the
2987 // top controls height.
2988 host_impl_->top_controls_manager()->ScrollBegin();
2989 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2990 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2991 host_impl_->top_controls_manager()->ScrollBy(top_controls_scroll_delta);
2992 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
2993 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_),
2994 outer_viewport_scroll_layer->FixedContainerSizeDelta());
2995 host_impl_->ScrollEnd();
2997 // Scroll in the direction to make the top controls show.
2998 host_impl_->top_controls_manager()->ScrollBegin();
2999 host_impl_->top_controls_manager()->ScrollBy(-top_controls_scroll_delta);
3000 EXPECT_EQ(top_controls_scroll_delta.y(),
3001 host_impl_->top_controls_manager()->ContentTopOffset());
3002 EXPECT_VECTOR_EQ(
3003 gfx::Vector2dF(0, top_controls_height_ - top_controls_scroll_delta.y()),
3004 outer_viewport_scroll_layer->FixedContainerSizeDelta());
3005 host_impl_->top_controls_manager()->ScrollEnd();
3008 // Test that if only the top controls are scrolled, we shouldn't request a
3009 // commit.
3010 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsDontTriggerCommit) {
3011 SetupTopControlsAndScrollLayerWithVirtualViewport(
3012 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3013 DrawFrame();
3015 // Show top controls
3016 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3018 // Scroll 25px to hide top controls
3019 gfx::Vector2dF scroll_delta(0.f, 25.f);
3020 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3021 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3022 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3023 EXPECT_FALSE(did_request_commit_);
3026 // Test that if a scrollable sublayer doesn't consume the scroll,
3027 // top controls should hide when scrolling down.
3028 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollableSublayer) {
3029 gfx::Size sub_content_size(100, 400);
3030 gfx::Size sub_content_layer_size(100, 300);
3031 SetupTopControlsAndScrollLayerWithVirtualViewport(
3032 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3033 DrawFrame();
3035 // Show top controls
3036 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3038 LayerImpl* outer_viewport_scroll_layer =
3039 host_impl_->active_tree()->OuterViewportScrollLayer();
3040 int id = outer_viewport_scroll_layer->id();
3042 scoped_ptr<LayerImpl> child =
3043 LayerImpl::Create(host_impl_->active_tree(), id + 2);
3044 scoped_ptr<LayerImpl> child_clip =
3045 LayerImpl::Create(host_impl_->active_tree(), id + 3);
3047 child_clip->SetBounds(sub_content_layer_size);
3048 child->SetScrollClipLayer(child_clip->id());
3049 child->SetBounds(sub_content_size);
3050 child->SetPosition(gfx::PointF());
3051 child->SetDrawsContent(true);
3052 child->SetIsContainerForFixedPositionLayers(true);
3054 // scroll child to limit
3055 child->SetScrollDelta(gfx::Vector2dF(0, 100.f));
3056 child_clip->AddChild(child.Pass());
3057 outer_viewport_scroll_layer->AddChild(child_clip.Pass());
3059 // Scroll 25px to hide top controls
3060 gfx::Vector2dF scroll_delta(0.f, 25.f);
3061 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3062 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3063 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3064 host_impl_->ScrollEnd();
3066 // Top controls should be hidden
3067 EXPECT_EQ(scroll_delta.y(),
3068 top_controls_height_ -
3069 host_impl_->top_controls_manager()->ContentTopOffset());
3072 // Ensure setting the top controls position explicitly using the setters on the
3073 // TreeImpl correctly affects the top controls manager and viewport bounds.
3074 TEST_F(LayerTreeHostImplTopControlsTest, PositionTopControlsExplicitly) {
3075 CreateHostImpl(settings_, CreateOutputSurface());
3076 SetupTopControlsAndScrollLayerWithVirtualViewport(
3077 layer_size_, layer_size_, layer_size_);
3078 DrawFrame();
3080 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3081 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3082 30.f / top_controls_height_);
3083 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3084 EXPECT_FLOAT_EQ(30.f, host_impl_->top_controls_manager()->ContentTopOffset());
3085 EXPECT_FLOAT_EQ(-20.f,
3086 host_impl_->top_controls_manager()->ControlsTopOffset());
3088 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3089 EXPECT_FLOAT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3090 EXPECT_FLOAT_EQ(-50.f,
3091 host_impl_->top_controls_manager()->ControlsTopOffset());
3093 host_impl_->DidChangeTopControlsPosition();
3095 // Now that top controls have moved, expect the clip to resize.
3096 LayerImpl* inner_clip_ptr =
3097 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3098 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3101 // Test that the top_controls delta and sent delta are appropriately
3102 // applied on sync tree activation. The total top controls offset shouldn't
3103 // change after the activation.
3104 TEST_F(LayerTreeHostImplTopControlsTest, ApplyDeltaOnTreeActivation) {
3105 CreateHostImpl(settings_, CreateOutputSurface());
3106 SetupTopControlsAndScrollLayerWithVirtualViewport(
3107 layer_size_, layer_size_, layer_size_);
3108 DrawFrame();
3110 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3111 20.f / top_controls_height_);
3112 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3113 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(
3114 15.f / top_controls_height_);
3115 host_impl_->active_tree()
3116 ->top_controls_shown_ratio()
3117 ->PullDeltaForMainThread();
3118 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3119 host_impl_->sync_tree()->PushTopControlsFromMainThread(15.f /
3120 top_controls_height_);
3122 host_impl_->DidChangeTopControlsPosition();
3123 LayerImpl* inner_clip_ptr =
3124 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3125 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3126 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3128 host_impl_->ActivateSyncTree();
3130 inner_clip_ptr = host_impl_->InnerViewportScrollLayer()->parent()->parent();
3131 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3132 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3134 EXPECT_FLOAT_EQ(
3135 -15.f, host_impl_->active_tree()->top_controls_shown_ratio()->Delta() *
3136 top_controls_height_);
3137 EXPECT_FLOAT_EQ(
3138 15.f,
3139 host_impl_->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3140 top_controls_height_);
3143 // Test that changing the top controls layout height is correctly applied to
3144 // the inner viewport container bounds. That is, the top controls layout
3145 // height is the amount that the inner viewport container was shrunk outside
3146 // the compositor to accommodate the top controls.
3147 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsLayoutHeightChanged) {
3148 CreateHostImpl(settings_, CreateOutputSurface());
3149 SetupTopControlsAndScrollLayerWithVirtualViewport(
3150 layer_size_, layer_size_, layer_size_);
3151 DrawFrame();
3153 host_impl_->sync_tree()->PushTopControlsFromMainThread(1.f);
3154 host_impl_->sync_tree()->set_top_controls_shrink_blink_size(true);
3156 host_impl_->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3157 1.f);
3158 host_impl_->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3159 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(0.f);
3161 host_impl_->DidChangeTopControlsPosition();
3162 LayerImpl* inner_clip_ptr =
3163 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3164 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3165 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3167 host_impl_->sync_tree()->root_layer()->SetBounds(
3168 gfx::Size(inner_clip_ptr->bounds().width(),
3169 inner_clip_ptr->bounds().height() - 50.f));
3171 host_impl_->ActivateSyncTree();
3173 inner_clip_ptr =
3174 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3175 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3177 // The total bounds should remain unchanged since the bounds delta should
3178 // account for the difference between the layout height and the current
3179 // top controls offset.
3180 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3181 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 50.f), inner_clip_ptr->bounds_delta());
3183 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
3184 host_impl_->DidChangeTopControlsPosition();
3186 EXPECT_EQ(1.f, host_impl_->top_controls_manager()->TopControlsShownRatio());
3187 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->TopControlsHeight());
3188 EXPECT_EQ(50.f, host_impl_->top_controls_manager()->ContentTopOffset());
3189 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f, 0.f), inner_clip_ptr->bounds_delta());
3190 EXPECT_EQ(gfx::Size(viewport_size_.width(), viewport_size_.height() - 50.f),
3191 inner_clip_ptr->bounds());
3194 // Test that showing/hiding the top controls when the viewport is fully scrolled
3195 // doesn't incorrectly change the viewport offset due to clamping from changing
3196 // viewport bounds.
3197 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsViewportOffsetClamping) {
3198 SetupTopControlsAndScrollLayerWithVirtualViewport(
3199 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3200 DrawFrame();
3202 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3204 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
3205 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
3207 // Scroll the viewports to max scroll offset.
3208 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3209 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3211 gfx::ScrollOffset viewport_offset =
3212 host_impl_->active_tree()->TotalScrollOffset();
3213 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(), viewport_offset);
3215 // Hide the top controls by 25px.
3216 gfx::Vector2dF scroll_delta(0.f, 25.f);
3217 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3218 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3219 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3221 // scrolling down at the max extents no longer hides the top controls
3222 EXPECT_EQ(1.f, host_impl_->active_tree()->CurrentTopControlsShownRatio());
3224 // forcefully hide the top controls by 25px
3225 host_impl_->top_controls_manager()->ScrollBy(scroll_delta);
3226 host_impl_->ScrollEnd();
3228 EXPECT_FLOAT_EQ(scroll_delta.y(),
3229 top_controls_height_ -
3230 host_impl_->top_controls_manager()->ContentTopOffset());
3232 inner_scroll->ClampScrollToMaxScrollOffset();
3233 outer_scroll->ClampScrollToMaxScrollOffset();
3235 // We should still be fully scrolled.
3236 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3237 host_impl_->active_tree()->TotalScrollOffset());
3239 viewport_offset = host_impl_->active_tree()->TotalScrollOffset();
3241 // Bring the top controls down by 25px.
3242 scroll_delta = gfx::Vector2dF(0.f, -25.f);
3243 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3244 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3245 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3246 host_impl_->ScrollEnd();
3248 // The viewport offset shouldn't have changed.
3249 EXPECT_EQ(viewport_offset,
3250 host_impl_->active_tree()->TotalScrollOffset());
3252 // Scroll the viewports to max scroll offset.
3253 outer_scroll->SetScrollDelta(gfx::Vector2dF(0, 200.f));
3254 inner_scroll->SetScrollDelta(gfx::Vector2dF(100, 100.f));
3255 EXPECT_EQ(host_impl_->active_tree()->TotalMaxScrollOffset(),
3256 host_impl_->active_tree()->TotalScrollOffset());
3259 // Test that the top controls coming in and out maintains the same aspect ratio
3260 // between the inner and outer viewports.
3261 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsAspectRatio) {
3262 SetupTopControlsAndScrollLayerWithVirtualViewport(
3263 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3264 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 2.f);
3265 DrawFrame();
3267 EXPECT_FLOAT_EQ(top_controls_height_,
3268 host_impl_->top_controls_manager()->ContentTopOffset());
3270 gfx::Vector2dF scroll_delta(0.f, 25.f);
3271 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3272 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3273 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3274 host_impl_->ScrollEnd();
3276 EXPECT_FLOAT_EQ(scroll_delta.y(),
3277 top_controls_height_ -
3278 host_impl_->top_controls_manager()->ContentTopOffset());
3280 // Top controls were hidden by 25px so the inner viewport should have expanded
3281 // by that much.
3282 LayerImpl* outer_container =
3283 host_impl_->active_tree()->OuterViewportContainerLayer();
3284 LayerImpl* inner_container =
3285 host_impl_->active_tree()->InnerViewportContainerLayer();
3286 EXPECT_EQ(gfx::Size(100, 100+25), inner_container->BoundsForScrolling());
3288 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3289 float aspect_ratio = inner_container->BoundsForScrolling().width() /
3290 inner_container->BoundsForScrolling().height();
3291 gfx::Size expected = gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio));
3292 EXPECT_EQ(expected, outer_container->BoundsForScrolling());
3293 EXPECT_EQ(expected,
3294 host_impl_->InnerViewportScrollLayer()->BoundsForScrolling());
3297 // Test that scrolling the outer viewport affects the top controls.
3298 TEST_F(LayerTreeHostImplTopControlsTest, TopControlsScrollOuterViewport) {
3299 SetupTopControlsAndScrollLayerWithVirtualViewport(
3300 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3301 DrawFrame();
3303 EXPECT_EQ(top_controls_height_,
3304 host_impl_->top_controls_manager()->ContentTopOffset());
3306 // Send a gesture scroll that will scroll the outer viewport, make sure the
3307 // top controls get scrolled.
3308 gfx::Vector2dF scroll_delta(0.f, 15.f);
3309 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3310 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3311 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3312 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3313 host_impl_->CurrentlyScrollingLayer());
3314 host_impl_->ScrollEnd();
3316 EXPECT_FLOAT_EQ(scroll_delta.y(),
3317 top_controls_height_ -
3318 host_impl_->top_controls_manager()->ContentTopOffset());
3320 scroll_delta = gfx::Vector2dF(0.f, 50.f);
3321 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3322 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3323 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3325 EXPECT_EQ(0, host_impl_->top_controls_manager()->ContentTopOffset());
3326 EXPECT_EQ(host_impl_->OuterViewportScrollLayer(),
3327 host_impl_->CurrentlyScrollingLayer());
3329 host_impl_->ScrollEnd();
3331 // Position the viewports such that the inner viewport will be scrolled.
3332 gfx::Vector2dF inner_viewport_offset(0.f, 25.f);
3333 host_impl_->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3334 host_impl_->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset);
3336 scroll_delta = gfx::Vector2dF(0.f, -65.f);
3337 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3338 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3339 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3341 EXPECT_EQ(top_controls_height_,
3342 host_impl_->top_controls_manager()->ContentTopOffset());
3343 EXPECT_FLOAT_EQ(
3344 inner_viewport_offset.y() + (scroll_delta.y() + top_controls_height_),
3345 host_impl_->InnerViewportScrollLayer()->ScrollDelta().y());
3347 host_impl_->ScrollEnd();
3350 TEST_F(LayerTreeHostImplTopControlsTest,
3351 ScrollNonScrollableRootWithTopControls) {
3352 CreateHostImpl(settings_, CreateOutputSurface());
3353 SetupTopControlsAndScrollLayerWithVirtualViewport(
3354 layer_size_, layer_size_, layer_size_);
3355 DrawFrame();
3357 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3358 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3360 host_impl_->top_controls_manager()->ScrollBegin();
3361 host_impl_->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f, 50.f));
3362 host_impl_->top_controls_manager()->ScrollEnd();
3363 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ContentTopOffset());
3364 // Now that top controls have moved, expect the clip to resize.
3365 LayerImpl* inner_clip_ptr =
3366 host_impl_->InnerViewportScrollLayer()->parent()->parent();
3367 EXPECT_EQ(viewport_size_, inner_clip_ptr->bounds());
3369 host_impl_->ScrollEnd();
3371 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3372 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3374 float scroll_increment_y = -25.f;
3375 host_impl_->top_controls_manager()->ScrollBegin();
3376 host_impl_->top_controls_manager()->ScrollBy(
3377 gfx::Vector2dF(0.f, scroll_increment_y));
3378 EXPECT_FLOAT_EQ(-scroll_increment_y,
3379 host_impl_->top_controls_manager()->ContentTopOffset());
3380 // Now that top controls have moved, expect the clip to resize.
3381 EXPECT_EQ(gfx::Size(viewport_size_.width(),
3382 viewport_size_.height() + scroll_increment_y),
3383 inner_clip_ptr->bounds());
3385 host_impl_->top_controls_manager()->ScrollBy(
3386 gfx::Vector2dF(0.f, scroll_increment_y));
3387 host_impl_->top_controls_manager()->ScrollEnd();
3388 EXPECT_FLOAT_EQ(-2 * scroll_increment_y,
3389 host_impl_->top_controls_manager()->ContentTopOffset());
3390 // Now that top controls have moved, expect the clip to resize.
3391 EXPECT_EQ(clip_size_, inner_clip_ptr->bounds());
3393 host_impl_->ScrollEnd();
3395 // Verify the layer is once-again non-scrollable.
3396 EXPECT_EQ(
3397 gfx::ScrollOffset(),
3398 host_impl_->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3400 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3401 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3404 TEST_F(LayerTreeHostImplTest, ScrollNonCompositedRoot) {
3405 // Test the configuration where a non-composited root layer is embedded in a
3406 // scrollable outer layer.
3407 gfx::Size surface_size(10, 10);
3408 gfx::Size contents_size(20, 20);
3410 scoped_ptr<LayerImpl> content_layer =
3411 LayerImpl::Create(host_impl_->active_tree(), 1);
3412 content_layer->SetDrawsContent(true);
3413 content_layer->SetPosition(gfx::PointF());
3414 content_layer->SetBounds(contents_size);
3416 scoped_ptr<LayerImpl> scroll_clip_layer =
3417 LayerImpl::Create(host_impl_->active_tree(), 3);
3418 scroll_clip_layer->SetBounds(surface_size);
3420 scoped_ptr<LayerImpl> scroll_layer =
3421 LayerImpl::Create(host_impl_->active_tree(), 2);
3422 scroll_layer->SetScrollClipLayer(3);
3423 scroll_layer->SetBounds(contents_size);
3424 scroll_layer->SetPosition(gfx::PointF());
3425 scroll_layer->AddChild(content_layer.Pass());
3426 scroll_clip_layer->AddChild(scroll_layer.Pass());
3428 scroll_clip_layer->SetHasRenderSurface(true);
3429 host_impl_->active_tree()->SetRootLayer(scroll_clip_layer.Pass());
3430 host_impl_->SetViewportSize(surface_size);
3431 DrawFrame();
3433 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3434 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3435 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3436 host_impl_->ScrollEnd();
3437 EXPECT_TRUE(did_request_redraw_);
3438 EXPECT_TRUE(did_request_commit_);
3441 TEST_F(LayerTreeHostImplTest, ScrollChildCallsCommitAndRedraw) {
3442 gfx::Size surface_size(10, 10);
3443 gfx::Size contents_size(20, 20);
3444 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3445 root->SetBounds(surface_size);
3446 root->AddChild(CreateScrollableLayer(2, contents_size, root.get()));
3447 root->SetHasRenderSurface(true);
3448 host_impl_->active_tree()->SetRootLayer(root.Pass());
3449 host_impl_->SetViewportSize(surface_size);
3450 DrawFrame();
3452 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3453 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3454 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3455 host_impl_->ScrollEnd();
3456 EXPECT_TRUE(did_request_redraw_);
3457 EXPECT_TRUE(did_request_commit_);
3460 TEST_F(LayerTreeHostImplTest, ScrollMissesChild) {
3461 gfx::Size surface_size(10, 10);
3462 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3463 root->AddChild(CreateScrollableLayer(2, surface_size, root.get()));
3464 root->SetHasRenderSurface(true);
3465 host_impl_->active_tree()->SetRootLayer(root.Pass());
3466 host_impl_->SetViewportSize(surface_size);
3467 DrawFrame();
3469 // Scroll event is ignored because the input coordinate is outside the layer
3470 // boundaries.
3471 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3472 host_impl_->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL));
3473 EXPECT_FALSE(did_request_redraw_);
3474 EXPECT_FALSE(did_request_commit_);
3477 TEST_F(LayerTreeHostImplTest, ScrollMissesBackfacingChild) {
3478 gfx::Size surface_size(10, 10);
3479 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3480 root->SetHasRenderSurface(true);
3481 scoped_ptr<LayerImpl> child =
3482 CreateScrollableLayer(2, surface_size, root.get());
3483 host_impl_->SetViewportSize(surface_size);
3485 gfx::Transform matrix;
3486 matrix.RotateAboutXAxis(180.0);
3487 child->SetTransform(matrix);
3488 child->SetDoubleSided(false);
3490 root->AddChild(child.Pass());
3491 host_impl_->active_tree()->SetRootLayer(root.Pass());
3492 DrawFrame();
3494 // Scroll event is ignored because the scrollable layer is not facing the
3495 // viewer and there is nothing scrollable behind it.
3496 EXPECT_EQ(InputHandler::SCROLL_IGNORED,
3497 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3498 EXPECT_FALSE(did_request_redraw_);
3499 EXPECT_FALSE(did_request_commit_);
3502 TEST_F(LayerTreeHostImplTest, ScrollBlockedByContentLayer) {
3503 gfx::Size surface_size(10, 10);
3504 scoped_ptr<LayerImpl> clip_layer =
3505 LayerImpl::Create(host_impl_->active_tree(), 3);
3506 scoped_ptr<LayerImpl> content_layer =
3507 CreateScrollableLayer(1, surface_size, clip_layer.get());
3508 content_layer->SetShouldScrollOnMainThread(true);
3509 content_layer->SetScrollClipLayer(Layer::INVALID_ID);
3511 // Note: we can use the same clip layer for both since both calls to
3512 // CreateScrollableLayer() use the same surface size.
3513 scoped_ptr<LayerImpl> scroll_layer =
3514 CreateScrollableLayer(2, surface_size, clip_layer.get());
3515 scroll_layer->AddChild(content_layer.Pass());
3516 clip_layer->AddChild(scroll_layer.Pass());
3517 clip_layer->SetHasRenderSurface(true);
3519 host_impl_->active_tree()->SetRootLayer(clip_layer.Pass());
3520 host_impl_->SetViewportSize(surface_size);
3521 DrawFrame();
3523 // Scrolling fails because the content layer is asking to be scrolled on the
3524 // main thread.
3525 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD,
3526 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3529 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnMainThread) {
3530 gfx::Size viewport_size(10, 10);
3531 float page_scale = 2.f;
3533 SetupScrollAndContentsLayers(viewport_size);
3535 // Setup the layers so that the outer viewport is scrollable.
3536 host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3537 viewport_size);
3538 host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
3539 gfx::Size(20, 20));
3540 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3541 DrawFrame();
3543 LayerImpl* root_scroll =
3544 host_impl_->active_tree()->OuterViewportScrollLayer();
3545 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3547 gfx::Vector2d scroll_delta(0, 10);
3548 gfx::Vector2d expected_scroll_delta = scroll_delta;
3549 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3550 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3551 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3552 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3553 host_impl_->ScrollEnd();
3555 // Set new page scale from main thread.
3556 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f, 2.f);
3558 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3559 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
3560 expected_scroll_delta));
3562 // The scroll range should also have been updated.
3563 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3565 // The page scale delta remains constant because the impl thread did not
3566 // scale.
3567 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3570 TEST_F(LayerTreeHostImplTest, ScrollRootAndChangePageScaleOnImplThread) {
3571 gfx::Size viewport_size(10, 10);
3572 float page_scale = 2.f;
3574 SetupScrollAndContentsLayers(viewport_size);
3576 // Setup the layers so that the outer viewport is scrollable.
3577 host_impl_->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3578 viewport_size);
3579 host_impl_->active_tree()->OuterViewportScrollLayer()->SetBounds(
3580 gfx::Size(20, 20));
3581 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3582 DrawFrame();
3584 LayerImpl* root_scroll =
3585 host_impl_->active_tree()->OuterViewportScrollLayer();
3586 EXPECT_EQ(viewport_size, root_scroll->scroll_clip_layer()->bounds());
3588 gfx::Vector2d scroll_delta(0, 10);
3589 gfx::Vector2d expected_scroll_delta = scroll_delta;
3590 gfx::ScrollOffset expected_max_scroll = root_scroll->MaxScrollOffset();
3591 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3592 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3593 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3594 host_impl_->ScrollEnd();
3596 // Set new page scale on impl thread by pinching.
3597 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3598 host_impl_->PinchGestureBegin();
3599 host_impl_->PinchGestureUpdate(page_scale, gfx::Point());
3600 host_impl_->PinchGestureEnd();
3601 host_impl_->ScrollEnd();
3602 DrawOneFrame();
3604 // The scroll delta is not scaled because the main thread did not scale.
3605 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3606 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll->id(),
3607 expected_scroll_delta));
3609 // The scroll range should also have been updated.
3610 EXPECT_EQ(expected_max_scroll, root_scroll->MaxScrollOffset());
3612 // The page scale delta should match the new scale on the impl side.
3613 EXPECT_EQ(page_scale, host_impl_->active_tree()->current_page_scale_factor());
3616 TEST_F(LayerTreeHostImplTest, PageScaleDeltaAppliedToRootScrollLayerOnly) {
3617 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 1.f, 2.f);
3618 gfx::Size surface_size(10, 10);
3619 float default_page_scale = 1.f;
3620 gfx::Transform default_page_scale_matrix;
3621 default_page_scale_matrix.Scale(default_page_scale, default_page_scale);
3623 float new_page_scale = 2.f;
3624 gfx::Transform new_page_scale_matrix;
3625 new_page_scale_matrix.Scale(new_page_scale, new_page_scale);
3627 // Create a normal scrollable root layer and another scrollable child layer.
3628 LayerImpl* scroll = SetupScrollAndContentsLayers(surface_size);
3629 LayerImpl* root = host_impl_->active_tree()->root_layer();
3630 LayerImpl* child = scroll->children()[0];
3632 scoped_ptr<LayerImpl> scrollable_child_clip =
3633 LayerImpl::Create(host_impl_->active_tree(), 6);
3634 scoped_ptr<LayerImpl> scrollable_child =
3635 CreateScrollableLayer(7, surface_size, scrollable_child_clip.get());
3636 scrollable_child_clip->AddChild(scrollable_child.Pass());
3637 child->AddChild(scrollable_child_clip.Pass());
3638 LayerImpl* grand_child = child->children()[0];
3640 // Set new page scale on impl thread by pinching.
3641 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
3642 host_impl_->PinchGestureBegin();
3643 host_impl_->PinchGestureUpdate(new_page_scale, gfx::Point());
3644 host_impl_->PinchGestureEnd();
3645 host_impl_->ScrollEnd();
3646 DrawOneFrame();
3648 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3649 // the page scale delta on the root layer is applied hierarchically.
3650 LayerTreeHostImpl::FrameData frame;
3651 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
3652 host_impl_->DrawLayers(&frame);
3653 host_impl_->DidDrawAllLayers(frame);
3655 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(0, 0));
3656 EXPECT_EQ(1.f, root->draw_transform().matrix().getDouble(1, 1));
3657 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(0, 0));
3658 EXPECT_EQ(new_page_scale, scroll->draw_transform().matrix().getDouble(1, 1));
3659 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(0, 0));
3660 EXPECT_EQ(new_page_scale, child->draw_transform().matrix().getDouble(1, 1));
3661 EXPECT_EQ(new_page_scale,
3662 grand_child->draw_transform().matrix().getDouble(0, 0));
3663 EXPECT_EQ(new_page_scale,
3664 grand_child->draw_transform().matrix().getDouble(1, 1));
3667 TEST_F(LayerTreeHostImplTest, ScrollChildAndChangePageScaleOnMainThread) {
3668 gfx::Size surface_size(30, 30);
3669 SetupScrollAndContentsLayers(surface_size);
3671 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
3673 // Make the outer scroll layer scrollable.
3674 outer_scroll->SetBounds(gfx::Size(50, 50));
3676 DrawFrame();
3678 gfx::Vector2d scroll_delta(0, 10);
3679 gfx::Vector2d expected_scroll_delta(scroll_delta);
3680 gfx::ScrollOffset expected_max_scroll(outer_scroll->MaxScrollOffset());
3681 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3682 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3683 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3684 host_impl_->ScrollEnd();
3686 float page_scale = 2.f;
3687 host_impl_->active_tree()->PushPageScaleFromMainThread(page_scale, 1.f,
3688 page_scale);
3690 DrawOneFrame();
3692 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3693 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), outer_scroll->id(),
3694 expected_scroll_delta));
3696 // The scroll range should not have changed.
3697 EXPECT_EQ(outer_scroll->MaxScrollOffset(), expected_max_scroll);
3699 // The page scale delta remains constant because the impl thread did not
3700 // scale.
3701 EXPECT_EQ(1.f, host_impl_->active_tree()->page_scale_delta());
3704 TEST_F(LayerTreeHostImplTest, ScrollChildBeyondLimit) {
3705 // Scroll a child layer beyond its maximum scroll range and make sure the
3706 // parent layer is scrolled on the axis on which the child was unable to
3707 // scroll.
3708 gfx::Size surface_size(10, 10);
3709 gfx::Size content_size(20, 20);
3710 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3711 root->SetBounds(surface_size);
3712 root->SetHasRenderSurface(true);
3713 scoped_ptr<LayerImpl> grand_child =
3714 CreateScrollableLayer(3, content_size, root.get());
3716 scoped_ptr<LayerImpl> child =
3717 CreateScrollableLayer(2, content_size, root.get());
3718 LayerImpl* grand_child_layer = grand_child.get();
3719 child->AddChild(grand_child.Pass());
3721 LayerImpl* child_layer = child.get();
3722 root->AddChild(child.Pass());
3723 host_impl_->active_tree()->SetRootLayer(root.Pass());
3724 host_impl_->active_tree()->DidBecomeActive();
3725 host_impl_->SetViewportSize(surface_size);
3726 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3727 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3729 DrawFrame();
3731 gfx::Vector2d scroll_delta(-8, -7);
3732 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3733 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3734 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3735 host_impl_->ScrollEnd();
3737 scoped_ptr<ScrollAndScaleSet> scroll_info =
3738 host_impl_->ProcessScrollDeltas();
3740 // The grand child should have scrolled up to its limit.
3741 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
3742 LayerImpl* grand_child = child->children()[0];
3743 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3744 gfx::Vector2d(0, -5)));
3746 // The child should have only scrolled on the other axis.
3747 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
3748 gfx::Vector2d(-3, 0)));
3752 TEST_F(LayerTreeHostImplTest, ScrollWithoutBubbling) {
3753 // Scroll a child layer beyond its maximum scroll range and make sure the
3754 // the scroll doesn't bubble up to the parent layer.
3755 gfx::Size surface_size(20, 20);
3756 gfx::Size viewport_size(10, 10);
3757 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
3758 root->SetHasRenderSurface(true);
3759 scoped_ptr<LayerImpl> root_scrolling =
3760 CreateScrollableLayer(2, surface_size, root.get());
3761 root_scrolling->SetIsContainerForFixedPositionLayers(true);
3763 scoped_ptr<LayerImpl> grand_child =
3764 CreateScrollableLayer(4, surface_size, root.get());
3766 scoped_ptr<LayerImpl> child =
3767 CreateScrollableLayer(3, surface_size, root.get());
3768 LayerImpl* grand_child_layer = grand_child.get();
3769 child->AddChild(grand_child.Pass());
3771 LayerImpl* child_layer = child.get();
3772 root_scrolling->AddChild(child.Pass());
3773 root->AddChild(root_scrolling.Pass());
3774 EXPECT_EQ(viewport_size, root->bounds());
3775 host_impl_->active_tree()->SetRootLayer(root.Pass());
3776 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3777 Layer::INVALID_ID);
3778 host_impl_->active_tree()->DidBecomeActive();
3779 host_impl_->SetViewportSize(viewport_size);
3781 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3782 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3784 DrawFrame();
3786 gfx::Vector2d scroll_delta(0, -10);
3787 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3788 host_impl_->ScrollBegin(gfx::Point(),
3789 InputHandler::NON_BUBBLING_GESTURE));
3790 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3791 host_impl_->ScrollEnd();
3793 scoped_ptr<ScrollAndScaleSet> scroll_info =
3794 host_impl_->ProcessScrollDeltas();
3796 // The grand child should have scrolled up to its limit.
3797 LayerImpl* child =
3798 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
3799 LayerImpl* grand_child = child->children()[0];
3800 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3801 gfx::Vector2d(0, -2)));
3803 // The child should not have scrolled.
3804 ExpectNone(*scroll_info.get(), child->id());
3806 // The next time we scroll we should only scroll the parent.
3807 scroll_delta = gfx::Vector2d(0, -3);
3808 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3809 host_impl_->ScrollBegin(gfx::Point(5, 5),
3810 InputHandler::NON_BUBBLING_GESTURE));
3811 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3812 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3813 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
3814 host_impl_->ScrollEnd();
3816 scroll_info = host_impl_->ProcessScrollDeltas();
3818 // The child should have scrolled up to its limit.
3819 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
3820 gfx::Vector2d(0, -3)));
3822 // The grand child should not have scrolled.
3823 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3824 gfx::Vector2d(0, -2)));
3826 // After scrolling the parent, another scroll on the opposite direction
3827 // should still scroll the child.
3828 scroll_delta = gfx::Vector2d(0, 7);
3829 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3830 host_impl_->ScrollBegin(gfx::Point(5, 5),
3831 InputHandler::NON_BUBBLING_GESTURE));
3832 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3833 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3834 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
3835 host_impl_->ScrollEnd();
3837 scroll_info = host_impl_->ProcessScrollDeltas();
3839 // The grand child should have scrolled.
3840 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3841 gfx::Vector2d(0, 5)));
3843 // The child should not have scrolled.
3844 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child->id(),
3845 gfx::Vector2d(0, -3)));
3847 // Scrolling should be adjusted from viewport space.
3848 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 2.f, 2.f);
3849 host_impl_->SetPageScaleOnActiveTree(2.f);
3851 scroll_delta = gfx::Vector2d(0, -2);
3852 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3853 host_impl_->ScrollBegin(gfx::Point(1, 1),
3854 InputHandler::NON_BUBBLING_GESTURE));
3855 EXPECT_EQ(grand_child, host_impl_->CurrentlyScrollingLayer());
3856 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3857 host_impl_->ScrollEnd();
3859 scroll_info = host_impl_->ProcessScrollDeltas();
3861 // Should have scrolled by half the amount in layer space (5 - 2/2)
3862 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), grand_child->id(),
3863 gfx::Vector2d(0, 4)));
3866 TEST_F(LayerTreeHostImplTest, ScrollEventBubbling) {
3867 // When we try to scroll a non-scrollable child layer, the scroll delta
3868 // should be applied to one of its ancestors if possible.
3869 gfx::Size surface_size(10, 10);
3870 gfx::Size content_size(20, 20);
3871 scoped_ptr<LayerImpl> root_clip =
3872 LayerImpl::Create(host_impl_->active_tree(), 3);
3873 root_clip->SetHasRenderSurface(true);
3874 scoped_ptr<LayerImpl> root =
3875 CreateScrollableLayer(1, content_size, root_clip.get());
3876 // Make 'root' the clip layer for child: since they have the same sizes the
3877 // child will have zero max_scroll_offset and scrolls will bubble.
3878 scoped_ptr<LayerImpl> child =
3879 CreateScrollableLayer(2, content_size, root.get());
3880 child->SetIsContainerForFixedPositionLayers(true);
3881 root->SetBounds(content_size);
3883 int root_scroll_id = root->id();
3884 root->AddChild(child.Pass());
3885 root_clip->AddChild(root.Pass());
3887 host_impl_->SetViewportSize(surface_size);
3888 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3889 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 2,
3890 Layer::INVALID_ID);
3891 host_impl_->active_tree()->DidBecomeActive();
3892 DrawFrame();
3894 gfx::Vector2d scroll_delta(0, 4);
3895 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3896 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3897 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
3898 host_impl_->ScrollEnd();
3900 scoped_ptr<ScrollAndScaleSet> scroll_info =
3901 host_impl_->ProcessScrollDeltas();
3903 // Only the root scroll should have scrolled.
3904 ASSERT_EQ(scroll_info->scrolls.size(), 1u);
3905 EXPECT_TRUE(
3906 ScrollInfoContains(*scroll_info.get(), root_scroll_id, scroll_delta));
3910 TEST_F(LayerTreeHostImplTest, ScrollBeforeRedraw) {
3911 gfx::Size surface_size(10, 10);
3912 scoped_ptr<LayerImpl> root_clip =
3913 LayerImpl::Create(host_impl_->active_tree(), 1);
3914 scoped_ptr<LayerImpl> root_scroll =
3915 CreateScrollableLayer(2, surface_size, root_clip.get());
3916 root_scroll->SetIsContainerForFixedPositionLayers(true);
3917 root_clip->SetHasRenderSurface(true);
3918 root_clip->AddChild(root_scroll.Pass());
3919 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
3920 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 1, 2,
3921 Layer::INVALID_ID);
3922 host_impl_->active_tree()->DidBecomeActive();
3923 host_impl_->SetViewportSize(surface_size);
3925 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3926 // synchronization.
3927 DrawFrame();
3928 host_impl_->active_tree()->DetachLayerTree();
3929 scoped_ptr<LayerImpl> root_clip2 =
3930 LayerImpl::Create(host_impl_->active_tree(), 3);
3931 scoped_ptr<LayerImpl> root_scroll2 =
3932 CreateScrollableLayer(4, surface_size, root_clip2.get());
3933 root_scroll2->SetIsContainerForFixedPositionLayers(true);
3934 root_clip2->AddChild(root_scroll2.Pass());
3935 root_clip2->SetHasRenderSurface(true);
3936 host_impl_->active_tree()->SetRootLayer(root_clip2.Pass());
3937 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 4,
3938 Layer::INVALID_ID);
3939 host_impl_->active_tree()->DidBecomeActive();
3941 // Scrolling should still work even though we did not draw yet.
3942 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3943 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
3946 TEST_F(LayerTreeHostImplTest, ScrollAxisAlignedRotatedLayer) {
3947 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3949 // Rotate the root layer 90 degrees counter-clockwise about its center.
3950 gfx::Transform rotate_transform;
3951 rotate_transform.Rotate(-90.0);
3952 host_impl_->active_tree()->root_layer()->SetTransform(rotate_transform);
3954 gfx::Size surface_size(50, 50);
3955 host_impl_->SetViewportSize(surface_size);
3956 DrawFrame();
3958 // Scroll to the right in screen coordinates with a gesture.
3959 gfx::Vector2d gesture_scroll_delta(10, 0);
3960 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3961 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
3962 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
3963 host_impl_->ScrollEnd();
3965 // The layer should have scrolled down in its local coordinates.
3966 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
3967 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
3968 gfx::Vector2d(0, gesture_scroll_delta.x())));
3970 // Reset and scroll down with the wheel.
3971 scroll_layer->SetScrollDelta(gfx::Vector2dF());
3972 gfx::Vector2d wheel_scroll_delta(0, 10);
3973 EXPECT_EQ(InputHandler::SCROLL_STARTED,
3974 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
3975 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
3976 host_impl_->ScrollEnd();
3978 // The layer should have scrolled down in its local coordinates.
3979 scroll_info = host_impl_->ProcessScrollDeltas();
3980 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
3981 wheel_scroll_delta));
3984 TEST_F(LayerTreeHostImplTest, ScrollNonAxisAlignedRotatedLayer) {
3985 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
3986 int child_clip_layer_id = 6;
3987 int child_layer_id = 7;
3988 float child_layer_angle = -20.f;
3990 // Create a child layer that is rotated to a non-axis-aligned angle.
3991 scoped_ptr<LayerImpl> clip_layer =
3992 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
3993 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
3994 child_layer_id, scroll_layer->bounds(), clip_layer.get());
3995 gfx::Transform rotate_transform;
3996 rotate_transform.Translate(-50.0, -50.0);
3997 rotate_transform.Rotate(child_layer_angle);
3998 rotate_transform.Translate(50.0, 50.0);
3999 clip_layer->SetTransform(rotate_transform);
4001 // Only allow vertical scrolling.
4002 clip_layer->SetBounds(
4003 gfx::Size(child->bounds().width(), child->bounds().height() / 2));
4004 // The rotation depends on the layer's transform origin, and the child layer
4005 // is a different size than the clip, so make sure the clip layer's origin
4006 // lines up over the child.
4007 clip_layer->SetTransformOrigin(gfx::Point3F(
4008 clip_layer->bounds().width() * 0.5f, clip_layer->bounds().height(), 0.f));
4009 LayerImpl* child_ptr = child.get();
4010 clip_layer->AddChild(child.Pass());
4011 scroll_layer->AddChild(clip_layer.Pass());
4013 gfx::Size surface_size(50, 50);
4014 host_impl_->SetViewportSize(surface_size);
4015 DrawFrame();
4017 // Scroll down in screen coordinates with a gesture.
4018 gfx::Vector2d gesture_scroll_delta(0, 10);
4019 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4020 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4021 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4022 host_impl_->ScrollEnd();
4024 // The child layer should have scrolled down in its local coordinates an
4025 // amount proportional to the angle between it and the input scroll delta.
4026 gfx::Vector2d expected_scroll_delta(
4027 0, gesture_scroll_delta.y() *
4028 std::cos(MathUtil::Deg2Rad(child_layer_angle)));
4029 scoped_ptr<ScrollAndScaleSet> scroll_info =
4030 host_impl_->ProcessScrollDeltas();
4031 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4032 expected_scroll_delta));
4034 // The root scroll layer should not have scrolled, because the input delta
4035 // was close to the layer's axis of movement.
4036 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4039 // Now reset and scroll the same amount horizontally.
4040 child_ptr->SetScrollDelta(gfx::Vector2dF());
4041 gfx::Vector2d gesture_scroll_delta(10, 0);
4042 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4043 host_impl_->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE));
4044 host_impl_->ScrollBy(gfx::Point(), gesture_scroll_delta);
4045 host_impl_->ScrollEnd();
4047 // The child layer should have scrolled down in its local coordinates an
4048 // amount proportional to the angle between it and the input scroll delta.
4049 gfx::Vector2d expected_scroll_delta(
4050 0, -gesture_scroll_delta.x() *
4051 std::sin(MathUtil::Deg2Rad(child_layer_angle)));
4052 scoped_ptr<ScrollAndScaleSet> scroll_info =
4053 host_impl_->ProcessScrollDeltas();
4054 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4055 expected_scroll_delta));
4057 // The root scroll layer should have scrolled more, since the input scroll
4058 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4059 gfx::Vector2d expected_root_scroll_delta(
4060 gesture_scroll_delta.x() *
4061 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle)), 2),
4063 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4064 expected_root_scroll_delta));
4068 TEST_F(LayerTreeHostImplTest, ScrollPerspectiveTransformedLayer) {
4069 // When scrolling an element with perspective, the distance scrolled
4070 // depends on the point at which the scroll begins.
4071 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4072 int child_clip_layer_id = 6;
4073 int child_layer_id = 7;
4075 // Create a child layer that is rotated on its x axis, with perspective.
4076 scoped_ptr<LayerImpl> clip_layer =
4077 LayerImpl::Create(host_impl_->active_tree(), child_clip_layer_id);
4078 scoped_ptr<LayerImpl> child = CreateScrollableLayer(
4079 child_layer_id, scroll_layer->bounds(), clip_layer.get());
4080 LayerImpl* child_ptr = child.get();
4081 gfx::Transform perspective_transform;
4082 perspective_transform.Translate(-50.0, -50.0);
4083 perspective_transform.ApplyPerspectiveDepth(20);
4084 perspective_transform.RotateAboutXAxis(45);
4085 perspective_transform.Translate(50.0, 50.0);
4086 clip_layer->SetTransform(perspective_transform);
4088 clip_layer->SetBounds(gfx::Size(child_ptr->bounds().width() / 2,
4089 child_ptr->bounds().height() / 2));
4090 // The transform depends on the layer's transform origin, and the child layer
4091 // is a different size than the clip, so make sure the clip layer's origin
4092 // lines up over the child.
4093 clip_layer->SetTransformOrigin(gfx::Point3F(
4094 clip_layer->bounds().width(), clip_layer->bounds().height(), 0.f));
4095 clip_layer->AddChild(child.Pass());
4096 scroll_layer->AddChild(clip_layer.Pass());
4098 gfx::Size surface_size(50, 50);
4099 host_impl_->SetViewportSize(surface_size);
4101 scoped_ptr<ScrollAndScaleSet> scroll_info;
4103 gfx::Vector2d gesture_scroll_deltas[4];
4104 gesture_scroll_deltas[0] = gfx::Vector2d(4, 10);
4105 gesture_scroll_deltas[1] = gfx::Vector2d(4, 10);
4106 gesture_scroll_deltas[2] = gfx::Vector2d(10, 0);
4107 gesture_scroll_deltas[3] = gfx::Vector2d(10, 0);
4109 gfx::Vector2d expected_scroll_deltas[4];
4110 // Perspective affects the vertical delta by a different
4111 // amount depending on the vertical position of the |viewport_point|.
4112 expected_scroll_deltas[0] = gfx::Vector2d(2, 8);
4113 expected_scroll_deltas[1] = gfx::Vector2d(1, 4);
4114 // Deltas which start with the same vertical position of the
4115 // |viewport_point| are subject to identical perspective effects.
4116 expected_scroll_deltas[2] = gfx::Vector2d(4, 0);
4117 expected_scroll_deltas[3] = gfx::Vector2d(4, 0);
4119 gfx::Point viewport_point(1, 1);
4121 // Scroll in screen coordinates with a gesture. Each scroll starts
4122 // where the previous scroll ended, but the scroll position is reset
4123 // for each scroll.
4124 for (int i = 0; i < 4; ++i) {
4125 child_ptr->SetScrollDelta(gfx::Vector2dF());
4126 DrawFrame();
4127 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4128 host_impl_->ScrollBegin(viewport_point, InputHandler::GESTURE));
4129 host_impl_->ScrollBy(viewport_point, gesture_scroll_deltas[i]);
4130 viewport_point += gesture_scroll_deltas[i];
4131 host_impl_->ScrollEnd();
4133 scroll_info = host_impl_->ProcessScrollDeltas();
4134 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), child_layer_id,
4135 expected_scroll_deltas[i]));
4137 // The root scroll layer should not have scrolled, because the input delta
4138 // was close to the layer's axis of movement.
4139 EXPECT_EQ(scroll_info->scrolls.size(), 1u);
4143 TEST_F(LayerTreeHostImplTest, ScrollScaledLayer) {
4144 LayerImpl* scroll_layer =
4145 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4147 // Scale the layer to twice its normal size.
4148 int scale = 2;
4149 gfx::Transform scale_transform;
4150 scale_transform.Scale(scale, scale);
4151 scroll_layer->SetTransform(scale_transform);
4153 gfx::Size surface_size(50, 50);
4154 host_impl_->SetViewportSize(surface_size);
4155 DrawFrame();
4157 // Scroll down in screen coordinates with a gesture.
4158 gfx::Vector2d scroll_delta(0, 10);
4159 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4160 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4161 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4162 host_impl_->ScrollEnd();
4164 // The layer should have scrolled down in its local coordinates, but half the
4165 // amount.
4166 scoped_ptr<ScrollAndScaleSet> scroll_info = host_impl_->ProcessScrollDeltas();
4167 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4168 gfx::Vector2d(0, scroll_delta.y() / scale)));
4170 // Reset and scroll down with the wheel.
4171 scroll_layer->SetScrollDelta(gfx::Vector2dF());
4172 gfx::Vector2d wheel_scroll_delta(0, 10);
4173 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4174 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4175 host_impl_->ScrollBy(gfx::Point(), wheel_scroll_delta);
4176 host_impl_->ScrollEnd();
4178 // It should apply the scale factor to the scroll delta for the wheel event.
4179 scroll_info = host_impl_->ProcessScrollDeltas();
4180 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), scroll_layer->id(),
4181 wheel_scroll_delta));
4184 TEST_F(LayerTreeHostImplTest, ScrollViewportRounding) {
4185 int width = 332;
4186 int height = 20;
4187 int scale = 3;
4188 SetupScrollAndContentsLayers(gfx::Size(width, height));
4189 host_impl_->active_tree()->InnerViewportContainerLayer()->SetBounds(
4190 gfx::Size(width * scale - 1, height * scale));
4191 host_impl_->SetDeviceScaleFactor(scale);
4192 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4194 LayerImpl* inner_viewport_scroll_layer =
4195 host_impl_->active_tree()->InnerViewportScrollLayer();
4196 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4197 inner_viewport_scroll_layer->MaxScrollOffset());
4200 class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate {
4201 public:
4202 TestScrollOffsetDelegate()
4203 : page_scale_factor_(0.f),
4204 min_page_scale_factor_(-1.f),
4205 max_page_scale_factor_(-1.f),
4206 needs_animate_(false) {}
4208 ~TestScrollOffsetDelegate() override {}
4210 gfx::ScrollOffset GetTotalScrollOffset() override {
4211 return getter_return_value_;
4214 bool IsExternalScrollActive() const override { return false; }
4216 void SetNeedsAnimate(const AnimationCallback&) override {
4217 needs_animate_ = true;
4220 void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset,
4221 const gfx::ScrollOffset& max_scroll_offset,
4222 const gfx::SizeF& scrollable_size,
4223 float page_scale_factor,
4224 float min_page_scale_factor,
4225 float max_page_scale_factor) override {
4226 DCHECK(total_scroll_offset.x() <= max_scroll_offset.x());
4227 DCHECK(total_scroll_offset.y() <= max_scroll_offset.y());
4228 last_set_scroll_offset_ = total_scroll_offset;
4229 max_scroll_offset_ = max_scroll_offset;
4230 scrollable_size_ = scrollable_size;
4231 page_scale_factor_ = page_scale_factor;
4232 min_page_scale_factor_ = min_page_scale_factor;
4233 max_page_scale_factor_ = max_page_scale_factor;
4235 set_getter_return_value(last_set_scroll_offset_);
4238 bool GetAndResetNeedsAnimate() {
4239 bool needs_animate = needs_animate_;
4240 needs_animate_ = false;
4241 return needs_animate;
4244 gfx::ScrollOffset last_set_scroll_offset() {
4245 return last_set_scroll_offset_;
4248 void set_getter_return_value(const gfx::ScrollOffset& value) {
4249 getter_return_value_ = value;
4252 gfx::ScrollOffset max_scroll_offset() const {
4253 return max_scroll_offset_;
4256 gfx::SizeF scrollable_size() const {
4257 return scrollable_size_;
4260 float page_scale_factor() const {
4261 return page_scale_factor_;
4264 float min_page_scale_factor() const {
4265 return min_page_scale_factor_;
4268 float max_page_scale_factor() const {
4269 return max_page_scale_factor_;
4272 private:
4273 gfx::ScrollOffset last_set_scroll_offset_;
4274 gfx::ScrollOffset getter_return_value_;
4275 gfx::ScrollOffset max_scroll_offset_;
4276 gfx::SizeF scrollable_size_;
4277 float page_scale_factor_;
4278 float min_page_scale_factor_;
4279 float max_page_scale_factor_;
4280 bool needs_animate_;
4283 // TODO(jdduke): Test root fling animation.
4284 TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) {
4285 TestScrollOffsetDelegate scroll_delegate;
4286 host_impl_->SetViewportSize(gfx::Size(10, 20));
4287 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4288 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4289 clip_layer->SetBounds(gfx::Size(10, 20));
4291 // Setting the delegate results in the current scroll offset being set.
4292 gfx::Vector2dF initial_scroll_delta(10.f, 10.f);
4293 scroll_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4294 scroll_layer->SetScrollDelta(initial_scroll_delta);
4295 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4296 EXPECT_EQ(initial_scroll_delta.ToString(),
4297 scroll_delegate.last_set_scroll_offset().ToString());
4299 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4300 // page_scale_factor and {min|max}_page_scale_factor being set.
4301 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate.scrollable_size());
4302 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate.max_scroll_offset());
4303 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4304 EXPECT_EQ(1.f, scroll_delegate.min_page_scale_factor());
4305 EXPECT_EQ(1.f, scroll_delegate.max_page_scale_factor());
4307 // Updating page scale immediately updates the delegate.
4308 host_impl_->active_tree()->PushPageScaleFromMainThread(2.f, 0.5f, 4.f);
4309 EXPECT_EQ(2.f, scroll_delegate.page_scale_factor());
4310 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4311 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4312 host_impl_->SetPageScaleOnActiveTree(2.f * 1.5f);
4313 EXPECT_EQ(3.f, scroll_delegate.page_scale_factor());
4314 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4315 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4316 host_impl_->SetPageScaleOnActiveTree(2.f);
4317 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4318 EXPECT_EQ(1.f, scroll_delegate.page_scale_factor());
4319 EXPECT_EQ(0.5f, scroll_delegate.min_page_scale_factor());
4320 EXPECT_EQ(4.f, scroll_delegate.max_page_scale_factor());
4322 // The pinch gesture doesn't put the delegate into a state where the scroll
4323 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4324 // delegate).
4325 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
4326 host_impl_->PinchGestureBegin();
4327 host_impl_->PinchGestureUpdate(2.f, gfx::Point());
4328 host_impl_->PinchGestureUpdate(.5f, gfx::Point());
4329 host_impl_->PinchGestureEnd();
4330 host_impl_->ScrollEnd();
4332 // Scrolling should be relative to the offset as returned by the delegate.
4333 gfx::Vector2dF scroll_delta(0.f, 10.f);
4334 gfx::ScrollOffset current_offset(7.f, 8.f);
4336 scroll_delegate.set_getter_return_value(current_offset);
4337 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4338 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
4339 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4341 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4342 EXPECT_EQ(ScrollOffsetWithDelta(current_offset, scroll_delta),
4343 scroll_delegate.last_set_scroll_offset());
4345 current_offset = gfx::ScrollOffset(42.f, 41.f);
4346 scroll_delegate.set_getter_return_value(current_offset);
4347 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4348 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4349 EXPECT_EQ(current_offset + gfx::ScrollOffset(scroll_delta),
4350 scroll_delegate.last_set_scroll_offset());
4351 host_impl_->ScrollEnd();
4352 scroll_delegate.set_getter_return_value(gfx::ScrollOffset());
4353 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4355 // Forces a full tree synchronization and ensures that the scroll delegate
4356 // sees the correct size of the new tree.
4357 gfx::Size new_size(42, 24);
4358 host_impl_->CreatePendingTree();
4359 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f, 1.f);
4360 CreateScrollAndContentsLayers(host_impl_->pending_tree(), new_size);
4361 host_impl_->ActivateSyncTree();
4362 EXPECT_EQ(new_size, scroll_delegate.scrollable_size());
4364 // Un-setting the delegate should propagate the delegate's current offset to
4365 // the root scrollable layer.
4366 current_offset = gfx::ScrollOffset(13.f, 12.f);
4367 scroll_delegate.set_getter_return_value(current_offset);
4368 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4369 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4371 EXPECT_EQ(current_offset.ToString(),
4372 scroll_layer->CurrentScrollOffset().ToString());
4375 void CheckLayerScrollDelta(LayerImpl* layer, gfx::Vector2dF scroll_delta) {
4376 const gfx::Transform target_space_transform =
4377 layer->draw_properties().target_space_transform;
4378 EXPECT_TRUE(target_space_transform.IsScaleOrTranslation());
4379 gfx::Point translated_point;
4380 target_space_transform.TransformPoint(&translated_point);
4381 gfx::Point expected_point = gfx::Point() - ToRoundedVector2d(scroll_delta);
4382 EXPECT_EQ(expected_point.ToString(), translated_point.ToString());
4385 TEST_F(LayerTreeHostImplTest,
4386 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw) {
4387 TestScrollOffsetDelegate scroll_delegate;
4388 host_impl_->SetViewportSize(gfx::Size(10, 20));
4389 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
4390 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4391 clip_layer->SetBounds(gfx::Size(10, 20));
4392 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
4394 // Draw first frame to clear any pending draws and check scroll.
4395 DrawFrame();
4396 CheckLayerScrollDelta(scroll_layer, gfx::Vector2dF(0.f, 0.f));
4397 EXPECT_FALSE(host_impl_->active_tree()->needs_update_draw_properties());
4399 // Set external scroll delta on delegate and notify LayerTreeHost.
4400 gfx::ScrollOffset scroll_offset(10.f, 10.f);
4401 scroll_delegate.set_getter_return_value(scroll_offset);
4402 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
4404 // Check scroll delta reflected in layer.
4405 LayerTreeHostImpl::FrameData frame;
4406 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4407 host_impl_->DrawLayers(&frame);
4408 host_impl_->DidDrawAllLayers(frame);
4409 EXPECT_FALSE(frame.has_no_damage);
4410 CheckLayerScrollDelta(scroll_layer, ScrollOffsetToVector2dF(scroll_offset));
4412 host_impl_->SetRootLayerScrollOffsetDelegate(NULL);
4415 TEST_F(LayerTreeHostImplTest, OverscrollRoot) {
4416 InputHandlerScrollResult scroll_result;
4417 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4418 host_impl_->SetViewportSize(gfx::Size(50, 50));
4419 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4420 DrawFrame();
4421 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4423 // In-bounds scrolling does not affect overscroll.
4424 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4425 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4426 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4427 EXPECT_TRUE(scroll_result.did_scroll);
4428 EXPECT_FALSE(scroll_result.did_overscroll_root);
4429 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4430 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4432 // Overscroll events are reflected immediately.
4433 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4434 EXPECT_TRUE(scroll_result.did_scroll);
4435 EXPECT_TRUE(scroll_result.did_overscroll_root);
4436 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4437 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4438 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4439 host_impl_->accumulated_root_overscroll());
4441 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4442 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4443 EXPECT_TRUE(scroll_result.did_scroll);
4444 EXPECT_FALSE(scroll_result.did_overscroll_root);
4445 EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta);
4446 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4447 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4448 host_impl_->accumulated_root_overscroll());
4450 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4451 EXPECT_FALSE(scroll_result.did_scroll);
4452 EXPECT_TRUE(scroll_result.did_overscroll_root);
4453 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4454 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4455 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4456 host_impl_->accumulated_root_overscroll());
4458 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4459 EXPECT_TRUE(scroll_result.did_scroll);
4460 EXPECT_FALSE(scroll_result.did_overscroll_root);
4461 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4462 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4463 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4464 host_impl_->accumulated_root_overscroll());
4466 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4467 EXPECT_TRUE(scroll_result.did_scroll);
4468 EXPECT_TRUE(scroll_result.did_overscroll_root);
4469 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta);
4470 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll());
4471 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4472 host_impl_->accumulated_root_overscroll());
4474 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4475 EXPECT_TRUE(scroll_result.did_scroll);
4476 EXPECT_TRUE(scroll_result.did_overscroll_root);
4477 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta);
4478 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll());
4479 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4480 host_impl_->accumulated_root_overscroll());
4482 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4483 EXPECT_TRUE(scroll_result.did_scroll);
4484 EXPECT_TRUE(scroll_result.did_overscroll_root);
4485 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4486 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4487 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4488 host_impl_->accumulated_root_overscroll());
4490 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4491 // as no scroll occurs.
4492 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4493 EXPECT_FALSE(scroll_result.did_scroll);
4494 EXPECT_TRUE(scroll_result.did_overscroll_root);
4495 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4496 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll());
4497 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4498 host_impl_->accumulated_root_overscroll());
4500 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4501 EXPECT_FALSE(scroll_result.did_scroll);
4502 EXPECT_TRUE(scroll_result.did_overscroll_root);
4503 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta);
4504 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll());
4505 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4506 host_impl_->accumulated_root_overscroll());
4508 // Overscroll resets on valid scroll.
4509 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4510 EXPECT_TRUE(scroll_result.did_scroll);
4511 EXPECT_FALSE(scroll_result.did_overscroll_root);
4512 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta);
4513 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll());
4514 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4515 host_impl_->accumulated_root_overscroll());
4517 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4518 EXPECT_TRUE(scroll_result.did_scroll);
4519 EXPECT_TRUE(scroll_result.did_overscroll_root);
4520 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta);
4521 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll());
4522 EXPECT_EQ(scroll_result.accumulated_root_overscroll,
4523 host_impl_->accumulated_root_overscroll());
4525 host_impl_->ScrollEnd();
4529 TEST_F(LayerTreeHostImplTest, OverscrollChildWithoutBubbling) {
4530 // Scroll child layers beyond their maximum scroll range and make sure root
4531 // overscroll does not accumulate.
4532 InputHandlerScrollResult scroll_result;
4533 gfx::Size surface_size(10, 10);
4534 scoped_ptr<LayerImpl> root_clip =
4535 LayerImpl::Create(host_impl_->active_tree(), 4);
4536 root_clip->SetHasRenderSurface(true);
4538 scoped_ptr<LayerImpl> root =
4539 CreateScrollableLayer(1, surface_size, root_clip.get());
4541 scoped_ptr<LayerImpl> grand_child =
4542 CreateScrollableLayer(3, surface_size, root_clip.get());
4544 scoped_ptr<LayerImpl> child =
4545 CreateScrollableLayer(2, surface_size, root_clip.get());
4546 LayerImpl* grand_child_layer = grand_child.get();
4547 child->AddChild(grand_child.Pass());
4549 LayerImpl* child_layer = child.get();
4550 root->AddChild(child.Pass());
4551 root_clip->AddChild(root.Pass());
4552 child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4553 grand_child_layer->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4554 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
4555 host_impl_->active_tree()->DidBecomeActive();
4556 host_impl_->SetViewportSize(surface_size);
4557 DrawFrame();
4559 gfx::Vector2d scroll_delta(0, -10);
4560 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4561 host_impl_->ScrollBegin(gfx::Point(),
4562 InputHandler::NON_BUBBLING_GESTURE));
4563 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4564 EXPECT_TRUE(scroll_result.did_scroll);
4565 EXPECT_FALSE(scroll_result.did_overscroll_root);
4566 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4567 host_impl_->ScrollEnd();
4569 // The next time we scroll we should only scroll the parent, but overscroll
4570 // should still not reach the root layer.
4571 scroll_delta = gfx::Vector2d(0, -30);
4572 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4573 host_impl_->ScrollBegin(gfx::Point(5, 5),
4574 InputHandler::NON_BUBBLING_GESTURE));
4575 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4576 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4577 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4578 EXPECT_TRUE(scroll_result.did_scroll);
4579 EXPECT_FALSE(scroll_result.did_overscroll_root);
4580 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_layer);
4581 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4582 host_impl_->ScrollEnd();
4584 // After scrolling the parent, another scroll on the opposite direction
4585 // should scroll the child.
4586 scroll_delta = gfx::Vector2d(0, 70);
4587 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4588 host_impl_->ScrollBegin(gfx::Point(5, 5),
4589 InputHandler::NON_BUBBLING_GESTURE));
4590 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4591 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4592 EXPECT_TRUE(scroll_result.did_scroll);
4593 EXPECT_FALSE(scroll_result.did_overscroll_root);
4594 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child_layer);
4595 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4596 host_impl_->ScrollEnd();
4600 TEST_F(LayerTreeHostImplTest, OverscrollChildEventBubbling) {
4601 // When we try to scroll a non-scrollable child layer, the scroll delta
4602 // should be applied to one of its ancestors if possible. Overscroll should
4603 // be reflected only when it has bubbled up to the root scrolling layer.
4604 InputHandlerScrollResult scroll_result;
4605 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4606 DrawFrame();
4608 gfx::Vector2d scroll_delta(0, 8);
4609 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4610 host_impl_->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL));
4611 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4612 EXPECT_TRUE(scroll_result.did_scroll);
4613 EXPECT_FALSE(scroll_result.did_overscroll_root);
4614 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4615 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4616 EXPECT_TRUE(scroll_result.did_scroll);
4617 EXPECT_TRUE(scroll_result.did_overscroll_root);
4618 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_->accumulated_root_overscroll());
4619 scroll_result = host_impl_->ScrollBy(gfx::Point(), scroll_delta);
4620 EXPECT_FALSE(scroll_result.did_scroll);
4621 EXPECT_TRUE(scroll_result.did_overscroll_root);
4622 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_->accumulated_root_overscroll());
4623 host_impl_->ScrollEnd();
4627 TEST_F(LayerTreeHostImplTest, OverscrollAlways) {
4628 InputHandlerScrollResult scroll_result;
4629 LayerTreeSettings settings;
4630 CreateHostImpl(settings, CreateOutputSurface());
4632 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(50, 50));
4633 LayerImpl* clip_layer = scroll_layer->parent()->parent();
4634 clip_layer->SetBounds(gfx::Size(50, 50));
4635 host_impl_->SetViewportSize(gfx::Size(50, 50));
4636 host_impl_->active_tree()->PushPageScaleFromMainThread(1.f, 0.5f, 4.f);
4637 DrawFrame();
4638 EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll());
4640 // Even though the layer can't scroll the overscroll still happens.
4641 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4642 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
4643 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4644 EXPECT_FALSE(scroll_result.did_scroll);
4645 EXPECT_TRUE(scroll_result.did_overscroll_root);
4646 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll());
4649 TEST_F(LayerTreeHostImplTest, NoOverscrollWhenNotAtEdge) {
4650 InputHandlerScrollResult scroll_result;
4651 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4653 DrawFrame();
4655 // Edge glow effect should be applicable only upon reaching Edges
4656 // of the content. unnecessary glow effect calls shouldn't be
4657 // called while scrolling up without reaching the edge of the content.
4658 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4659 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4660 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4661 EXPECT_TRUE(scroll_result.did_scroll);
4662 EXPECT_FALSE(scroll_result.did_overscroll_root);
4663 EXPECT_EQ(gfx::Vector2dF().ToString(),
4664 host_impl_->accumulated_root_overscroll().ToString());
4665 scroll_result =
4666 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
4667 EXPECT_TRUE(scroll_result.did_scroll);
4668 EXPECT_FALSE(scroll_result.did_overscroll_root);
4669 EXPECT_EQ(gfx::Vector2dF().ToString(),
4670 host_impl_->accumulated_root_overscroll().ToString());
4671 host_impl_->ScrollEnd();
4672 // unusedrootDelta should be subtracted from applied delta so that
4673 // unwanted glow effect calls are not called.
4674 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4675 host_impl_->ScrollBegin(gfx::Point(0, 0),
4676 InputHandler::NON_BUBBLING_GESTURE));
4677 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
4678 scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4679 EXPECT_TRUE(scroll_result.did_scroll);
4680 EXPECT_TRUE(scroll_result.did_overscroll_root);
4681 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4682 host_impl_->accumulated_root_overscroll().ToString());
4684 scroll_result =
4685 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f, -0.01f));
4686 EXPECT_FALSE(scroll_result.did_scroll);
4687 EXPECT_FALSE(scroll_result.did_overscroll_root);
4688 EXPECT_EQ(gfx::Vector2dF(0.000000f, 17.699997f).ToString(),
4689 host_impl_->accumulated_root_overscroll().ToString());
4690 host_impl_->ScrollEnd();
4691 // TestCase to check kEpsilon, which prevents minute values to trigger
4692 // gloweffect without reaching edge.
4693 EXPECT_EQ(InputHandler::SCROLL_STARTED,
4694 host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL));
4695 scroll_result =
4696 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f, 0.1f));
4697 EXPECT_FALSE(scroll_result.did_scroll);
4698 EXPECT_FALSE(scroll_result.did_overscroll_root);
4699 EXPECT_EQ(gfx::Vector2dF().ToString(),
4700 host_impl_->accumulated_root_overscroll().ToString());
4701 host_impl_->ScrollEnd();
4705 class BlendStateCheckLayer : public LayerImpl {
4706 public:
4707 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
4708 int id,
4709 ResourceProvider* resource_provider) {
4710 return make_scoped_ptr(
4711 new BlendStateCheckLayer(tree_impl, id, resource_provider));
4714 void AppendQuads(RenderPass* render_pass,
4715 AppendQuadsData* append_quads_data) override {
4716 quads_appended_ = true;
4718 gfx::Rect opaque_rect;
4719 if (contents_opaque())
4720 opaque_rect = quad_rect_;
4721 else
4722 opaque_rect = opaque_content_rect_;
4723 gfx::Rect visible_quad_rect = quad_rect_;
4725 SharedQuadState* shared_quad_state =
4726 render_pass->CreateAndAppendSharedQuadState();
4727 PopulateSharedQuadState(shared_quad_state);
4729 TileDrawQuad* test_blending_draw_quad =
4730 render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
4731 test_blending_draw_quad->SetNew(shared_quad_state,
4732 quad_rect_,
4733 opaque_rect,
4734 visible_quad_rect,
4735 resource_id_,
4736 gfx::RectF(0.f, 0.f, 1.f, 1.f),
4737 gfx::Size(1, 1),
4738 false,
4739 false);
4740 test_blending_draw_quad->visible_rect = quad_visible_rect_;
4741 EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
4742 EXPECT_EQ(has_render_surface_, !!render_surface());
4745 void SetExpectation(bool blend, bool has_render_surface) {
4746 blend_ = blend;
4747 has_render_surface_ = has_render_surface;
4748 quads_appended_ = false;
4751 bool quads_appended() const { return quads_appended_; }
4753 void SetQuadRect(const gfx::Rect& rect) { quad_rect_ = rect; }
4754 void SetQuadVisibleRect(const gfx::Rect& rect) { quad_visible_rect_ = rect; }
4755 void SetOpaqueContentRect(const gfx::Rect& rect) {
4756 opaque_content_rect_ = rect;
4759 private:
4760 BlendStateCheckLayer(LayerTreeImpl* tree_impl,
4761 int id,
4762 ResourceProvider* resource_provider)
4763 : LayerImpl(tree_impl, id),
4764 blend_(false),
4765 has_render_surface_(false),
4766 quads_appended_(false),
4767 quad_rect_(5, 5, 5, 5),
4768 quad_visible_rect_(5, 5, 5, 5),
4769 resource_id_(resource_provider->CreateResource(
4770 gfx::Size(1, 1),
4771 GL_CLAMP_TO_EDGE,
4772 ResourceProvider::TEXTURE_HINT_IMMUTABLE,
4773 RGBA_8888)) {
4774 resource_provider->AllocateForTesting(resource_id_);
4775 SetBounds(gfx::Size(10, 10));
4776 SetDrawsContent(true);
4779 bool blend_;
4780 bool has_render_surface_;
4781 bool quads_appended_;
4782 gfx::Rect quad_rect_;
4783 gfx::Rect opaque_content_rect_;
4784 gfx::Rect quad_visible_rect_;
4785 ResourceId resource_id_;
4788 TEST_F(LayerTreeHostImplTest, BlendingOffWhenDrawingOpaqueLayers) {
4790 scoped_ptr<LayerImpl> root =
4791 LayerImpl::Create(host_impl_->active_tree(), 1);
4792 root->SetBounds(gfx::Size(10, 10));
4793 root->SetDrawsContent(false);
4794 root->SetHasRenderSurface(true);
4795 host_impl_->active_tree()->SetRootLayer(root.Pass());
4797 LayerImpl* root = host_impl_->active_tree()->root_layer();
4799 root->AddChild(
4800 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4802 host_impl_->resource_provider()));
4803 BlendStateCheckLayer* layer1 =
4804 static_cast<BlendStateCheckLayer*>(root->children()[0]);
4805 layer1->SetPosition(gfx::PointF(2.f, 2.f));
4807 LayerTreeHostImpl::FrameData frame;
4809 // Opaque layer, drawn without blending.
4810 layer1->SetContentsOpaque(true);
4811 layer1->SetExpectation(false, false);
4812 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4813 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4814 host_impl_->DrawLayers(&frame);
4815 EXPECT_TRUE(layer1->quads_appended());
4816 host_impl_->DidDrawAllLayers(frame);
4818 // Layer with translucent content and painting, so drawn with blending.
4819 layer1->SetContentsOpaque(false);
4820 layer1->SetExpectation(true, false);
4821 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4822 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4823 host_impl_->DrawLayers(&frame);
4824 EXPECT_TRUE(layer1->quads_appended());
4825 host_impl_->DidDrawAllLayers(frame);
4827 // Layer with translucent opacity, drawn with blending.
4828 layer1->SetContentsOpaque(true);
4829 layer1->SetOpacity(0.5f);
4830 layer1->SetExpectation(true, false);
4831 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4832 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4833 host_impl_->DrawLayers(&frame);
4834 EXPECT_TRUE(layer1->quads_appended());
4835 host_impl_->DidDrawAllLayers(frame);
4837 // Layer with translucent opacity and painting, drawn with blending.
4838 layer1->SetContentsOpaque(true);
4839 layer1->SetOpacity(0.5f);
4840 layer1->SetExpectation(true, false);
4841 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4842 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4843 host_impl_->DrawLayers(&frame);
4844 EXPECT_TRUE(layer1->quads_appended());
4845 host_impl_->DidDrawAllLayers(frame);
4847 layer1->AddChild(
4848 BlendStateCheckLayer::Create(host_impl_->active_tree(),
4850 host_impl_->resource_provider()));
4851 BlendStateCheckLayer* layer2 =
4852 static_cast<BlendStateCheckLayer*>(layer1->children()[0]);
4853 layer2->SetPosition(gfx::PointF(4.f, 4.f));
4855 // 2 opaque layers, drawn without blending.
4856 layer1->SetContentsOpaque(true);
4857 layer1->SetOpacity(1.f);
4858 layer1->SetExpectation(false, false);
4859 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4860 layer2->SetContentsOpaque(true);
4861 layer2->SetOpacity(1.f);
4862 layer2->SetExpectation(false, false);
4863 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4864 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4865 host_impl_->DrawLayers(&frame);
4866 EXPECT_TRUE(layer1->quads_appended());
4867 EXPECT_TRUE(layer2->quads_appended());
4868 host_impl_->DidDrawAllLayers(frame);
4870 // Parent layer with translucent content, drawn with blending.
4871 // Child layer with opaque content, drawn without blending.
4872 layer1->SetContentsOpaque(false);
4873 layer1->SetExpectation(true, false);
4874 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4875 layer2->SetExpectation(false, false);
4876 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4877 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4878 host_impl_->DrawLayers(&frame);
4879 EXPECT_TRUE(layer1->quads_appended());
4880 EXPECT_TRUE(layer2->quads_appended());
4881 host_impl_->DidDrawAllLayers(frame);
4883 // Parent layer with translucent content but opaque painting, drawn without
4884 // blending.
4885 // Child layer with opaque content, drawn without blending.
4886 layer1->SetContentsOpaque(true);
4887 layer1->SetExpectation(false, false);
4888 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4889 layer2->SetExpectation(false, false);
4890 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4891 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4892 host_impl_->DrawLayers(&frame);
4893 EXPECT_TRUE(layer1->quads_appended());
4894 EXPECT_TRUE(layer2->quads_appended());
4895 host_impl_->DidDrawAllLayers(frame);
4897 // Parent layer with translucent opacity and opaque content. Since it has a
4898 // drawing child, it's drawn to a render surface which carries the opacity,
4899 // so it's itself drawn without blending.
4900 // Child layer with opaque content, drawn without blending (parent surface
4901 // carries the inherited opacity).
4902 layer1->SetContentsOpaque(true);
4903 layer1->SetOpacity(0.5f);
4904 layer1->SetHasRenderSurface(true);
4905 layer1->SetExpectation(false, true);
4906 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4907 layer2->SetExpectation(false, false);
4908 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4909 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4910 host_impl_->active_tree()->root_layer());
4911 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4912 host_impl_->DrawLayers(&frame);
4913 EXPECT_TRUE(layer1->quads_appended());
4914 EXPECT_TRUE(layer2->quads_appended());
4915 host_impl_->DidDrawAllLayers(frame);
4916 layer1->SetHasRenderSurface(false);
4918 // Draw again, but with child non-opaque, to make sure
4919 // layer1 not culled.
4920 layer1->SetContentsOpaque(true);
4921 layer1->SetOpacity(1.f);
4922 layer1->SetExpectation(false, false);
4923 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4924 layer2->SetContentsOpaque(true);
4925 layer2->SetOpacity(0.5f);
4926 layer2->SetExpectation(true, false);
4927 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4928 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4929 host_impl_->DrawLayers(&frame);
4930 EXPECT_TRUE(layer1->quads_appended());
4931 EXPECT_TRUE(layer2->quads_appended());
4932 host_impl_->DidDrawAllLayers(frame);
4934 // A second way of making the child non-opaque.
4935 layer1->SetContentsOpaque(true);
4936 layer1->SetOpacity(1.f);
4937 layer1->SetExpectation(false, false);
4938 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4939 layer2->SetContentsOpaque(false);
4940 layer2->SetOpacity(1.f);
4941 layer2->SetExpectation(true, false);
4942 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4943 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4944 host_impl_->DrawLayers(&frame);
4945 EXPECT_TRUE(layer1->quads_appended());
4946 EXPECT_TRUE(layer2->quads_appended());
4947 host_impl_->DidDrawAllLayers(frame);
4949 // And when the layer says its not opaque but is painted opaque, it is not
4950 // blended.
4951 layer1->SetContentsOpaque(true);
4952 layer1->SetOpacity(1.f);
4953 layer1->SetExpectation(false, false);
4954 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4955 layer2->SetContentsOpaque(true);
4956 layer2->SetOpacity(1.f);
4957 layer2->SetExpectation(false, false);
4958 layer2->SetUpdateRect(gfx::Rect(layer1->bounds()));
4959 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4960 host_impl_->DrawLayers(&frame);
4961 EXPECT_TRUE(layer1->quads_appended());
4962 EXPECT_TRUE(layer2->quads_appended());
4963 host_impl_->DidDrawAllLayers(frame);
4965 // Layer with partially opaque contents, drawn with blending.
4966 layer1->SetContentsOpaque(false);
4967 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4968 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4969 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4970 layer1->SetExpectation(true, false);
4971 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4972 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4973 host_impl_->DrawLayers(&frame);
4974 EXPECT_TRUE(layer1->quads_appended());
4975 host_impl_->DidDrawAllLayers(frame);
4977 // Layer with partially opaque contents partially culled, drawn with blending.
4978 layer1->SetContentsOpaque(false);
4979 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4980 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4981 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4982 layer1->SetExpectation(true, false);
4983 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4984 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4985 host_impl_->DrawLayers(&frame);
4986 EXPECT_TRUE(layer1->quads_appended());
4987 host_impl_->DidDrawAllLayers(frame);
4989 // Layer with partially opaque contents culled, drawn with blending.
4990 layer1->SetContentsOpaque(false);
4991 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4992 layer1->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4993 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4994 layer1->SetExpectation(true, false);
4995 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
4996 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
4997 host_impl_->DrawLayers(&frame);
4998 EXPECT_TRUE(layer1->quads_appended());
4999 host_impl_->DidDrawAllLayers(frame);
5001 // Layer with partially opaque contents and translucent contents culled, drawn
5002 // without blending.
5003 layer1->SetContentsOpaque(false);
5004 layer1->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5005 layer1->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5006 layer1->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5007 layer1->SetExpectation(false, false);
5008 layer1->SetUpdateRect(gfx::Rect(layer1->bounds()));
5009 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5010 host_impl_->DrawLayers(&frame);
5011 EXPECT_TRUE(layer1->quads_appended());
5012 host_impl_->DidDrawAllLayers(frame);
5015 class LayerTreeHostImplViewportCoveredTest : public LayerTreeHostImplTest {
5016 protected:
5017 LayerTreeHostImplViewportCoveredTest() :
5018 gutter_quad_material_(DrawQuad::SOLID_COLOR),
5019 child_(NULL),
5020 did_activate_pending_tree_(false) {}
5022 scoped_ptr<OutputSurface> CreateFakeOutputSurface(bool always_draw) {
5023 if (always_draw) {
5024 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5026 return FakeOutputSurface::Create3d();
5029 void SetupActiveTreeLayers() {
5030 host_impl_->active_tree()->set_background_color(SK_ColorGRAY);
5031 host_impl_->active_tree()->SetRootLayer(
5032 LayerImpl::Create(host_impl_->active_tree(), 1));
5033 host_impl_->active_tree()->root_layer()->SetHasRenderSurface(true);
5034 host_impl_->active_tree()->root_layer()->AddChild(
5035 BlendStateCheckLayer::Create(host_impl_->active_tree(),
5037 host_impl_->resource_provider()));
5038 child_ = static_cast<BlendStateCheckLayer*>(
5039 host_impl_->active_tree()->root_layer()->children()[0]);
5040 child_->SetExpectation(false, false);
5041 child_->SetContentsOpaque(true);
5044 // Expect no gutter rects.
5045 void TestLayerCoversFullViewport() {
5046 gfx::Rect layer_rect(viewport_size_);
5047 child_->SetPosition(layer_rect.origin());
5048 child_->SetBounds(layer_rect.size());
5049 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5050 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5052 LayerTreeHostImpl::FrameData frame;
5053 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5054 ASSERT_EQ(1u, frame.render_passes.size());
5056 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5057 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5058 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5060 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5061 host_impl_->DidDrawAllLayers(frame);
5064 // Expect fullscreen gutter rect.
5065 void TestEmptyLayer() {
5066 gfx::Rect layer_rect(0, 0, 0, 0);
5067 child_->SetPosition(layer_rect.origin());
5068 child_->SetBounds(layer_rect.size());
5069 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5070 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5072 LayerTreeHostImpl::FrameData frame;
5073 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5074 ASSERT_EQ(1u, frame.render_passes.size());
5076 EXPECT_EQ(1u, CountGutterQuads(frame.render_passes[0]->quad_list));
5077 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5078 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5080 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5081 host_impl_->DidDrawAllLayers(frame);
5084 // Expect four surrounding gutter rects.
5085 void TestLayerInMiddleOfViewport() {
5086 gfx::Rect layer_rect(500, 500, 200, 200);
5087 child_->SetPosition(layer_rect.origin());
5088 child_->SetBounds(layer_rect.size());
5089 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5090 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5092 LayerTreeHostImpl::FrameData frame;
5093 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5094 ASSERT_EQ(1u, frame.render_passes.size());
5096 EXPECT_EQ(4u, CountGutterQuads(frame.render_passes[0]->quad_list));
5097 EXPECT_EQ(5u, frame.render_passes[0]->quad_list.size());
5098 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5100 VerifyQuadsExactlyCoverViewport(frame.render_passes[0]->quad_list);
5101 host_impl_->DidDrawAllLayers(frame);
5104 // Expect no gutter rects.
5105 void TestLayerIsLargerThanViewport() {
5106 gfx::Rect layer_rect(viewport_size_.width() + 10,
5107 viewport_size_.height() + 10);
5108 child_->SetPosition(layer_rect.origin());
5109 child_->SetBounds(layer_rect.size());
5110 child_->SetQuadRect(gfx::Rect(layer_rect.size()));
5111 child_->SetQuadVisibleRect(gfx::Rect(layer_rect.size()));
5113 LayerTreeHostImpl::FrameData frame;
5114 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5115 ASSERT_EQ(1u, frame.render_passes.size());
5117 EXPECT_EQ(0u, CountGutterQuads(frame.render_passes[0]->quad_list));
5118 EXPECT_EQ(1u, frame.render_passes[0]->quad_list.size());
5119 ValidateTextureDrawQuads(frame.render_passes[0]->quad_list);
5121 host_impl_->DidDrawAllLayers(frame);
5124 void DidActivateSyncTree() override { did_activate_pending_tree_ = true; }
5126 void set_gutter_quad_material(DrawQuad::Material material) {
5127 gutter_quad_material_ = material;
5129 void set_gutter_texture_size(const gfx::Size& gutter_texture_size) {
5130 gutter_texture_size_ = gutter_texture_size;
5133 protected:
5134 size_t CountGutterQuads(const QuadList& quad_list) {
5135 size_t num_gutter_quads = 0;
5136 for (const auto& quad : quad_list) {
5137 num_gutter_quads += (quad->material == gutter_quad_material_) ? 1 : 0;
5139 return num_gutter_quads;
5142 void VerifyQuadsExactlyCoverViewport(const QuadList& quad_list) {
5143 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5144 quad_list, gfx::Rect(DipSizeToPixelSize(viewport_size_)));
5147 // Make sure that the texture coordinates match their expectations.
5148 void ValidateTextureDrawQuads(const QuadList& quad_list) {
5149 for (const auto& quad : quad_list) {
5150 if (quad->material != DrawQuad::TEXTURE_CONTENT)
5151 continue;
5152 const TextureDrawQuad* texture_quad = TextureDrawQuad::MaterialCast(quad);
5153 gfx::SizeF gutter_texture_size_pixels = gfx::ScaleSize(
5154 gutter_texture_size_, host_impl_->device_scale_factor());
5155 EXPECT_EQ(texture_quad->uv_top_left.x(),
5156 texture_quad->rect.x() / gutter_texture_size_pixels.width());
5157 EXPECT_EQ(texture_quad->uv_top_left.y(),
5158 texture_quad->rect.y() / gutter_texture_size_pixels.height());
5159 EXPECT_EQ(
5160 texture_quad->uv_bottom_right.x(),
5161 texture_quad->rect.right() / gutter_texture_size_pixels.width());
5162 EXPECT_EQ(
5163 texture_quad->uv_bottom_right.y(),
5164 texture_quad->rect.bottom() / gutter_texture_size_pixels.height());
5168 gfx::Size DipSizeToPixelSize(const gfx::Size& size) {
5169 return gfx::ToRoundedSize(
5170 gfx::ScaleSize(size, host_impl_->device_scale_factor()));
5173 DrawQuad::Material gutter_quad_material_;
5174 gfx::Size gutter_texture_size_;
5175 gfx::Size viewport_size_;
5176 BlendStateCheckLayer* child_;
5177 bool did_activate_pending_tree_;
5180 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCovered) {
5181 viewport_size_ = gfx::Size(1000, 1000);
5183 bool always_draw = false;
5184 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5186 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5187 SetupActiveTreeLayers();
5188 TestLayerCoversFullViewport();
5189 TestEmptyLayer();
5190 TestLayerInMiddleOfViewport();
5191 TestLayerIsLargerThanViewport();
5194 TEST_F(LayerTreeHostImplViewportCoveredTest, ViewportCoveredScaled) {
5195 viewport_size_ = gfx::Size(1000, 1000);
5197 bool always_draw = false;
5198 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5200 host_impl_->SetDeviceScaleFactor(2.f);
5201 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5202 SetupActiveTreeLayers();
5203 TestLayerCoversFullViewport();
5204 TestEmptyLayer();
5205 TestLayerInMiddleOfViewport();
5206 TestLayerIsLargerThanViewport();
5209 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeGrowViewportInvalid) {
5210 viewport_size_ = gfx::Size(1000, 1000);
5212 bool always_draw = true;
5213 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5215 // Pending tree to force active_tree size invalid. Not used otherwise.
5216 host_impl_->CreatePendingTree();
5217 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5218 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5220 SetupActiveTreeLayers();
5221 TestEmptyLayer();
5222 TestLayerInMiddleOfViewport();
5223 TestLayerIsLargerThanViewport();
5226 TEST_F(LayerTreeHostImplViewportCoveredTest, ActiveTreeShrinkViewportInvalid) {
5227 viewport_size_ = gfx::Size(1000, 1000);
5229 bool always_draw = true;
5230 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw));
5232 // Set larger viewport and activate it to active tree.
5233 host_impl_->CreatePendingTree();
5234 gfx::Size larger_viewport(viewport_size_.width() + 100,
5235 viewport_size_.height() + 100);
5236 host_impl_->SetViewportSize(DipSizeToPixelSize(larger_viewport));
5237 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5238 host_impl_->ActivateSyncTree();
5239 EXPECT_TRUE(did_activate_pending_tree_);
5240 EXPECT_FALSE(host_impl_->active_tree()->ViewportSizeInvalid());
5242 // Shrink pending tree viewport without activating.
5243 host_impl_->CreatePendingTree();
5244 host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
5245 EXPECT_TRUE(host_impl_->active_tree()->ViewportSizeInvalid());
5247 SetupActiveTreeLayers();
5248 TestEmptyLayer();
5249 TestLayerInMiddleOfViewport();
5250 TestLayerIsLargerThanViewport();
5253 class FakeDrawableLayerImpl: public LayerImpl {
5254 public:
5255 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5256 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl, id));
5258 protected:
5259 FakeDrawableLayerImpl(LayerTreeImpl* tree_impl, int id)
5260 : LayerImpl(tree_impl, id) {}
5263 // Only reshape when we know we are going to draw. Otherwise, the reshape
5264 // can leave the window at the wrong size if we never draw and the proper
5265 // viewport size is never set.
5266 TEST_F(LayerTreeHostImplTest, ReshapeNotCalledUntilDraw) {
5267 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5268 scoped_ptr<OutputSurface> output_surface(
5269 FakeOutputSurface::Create3d(provider));
5270 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5272 scoped_ptr<LayerImpl> root =
5273 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5274 root->SetBounds(gfx::Size(10, 10));
5275 root->SetDrawsContent(true);
5276 root->SetHasRenderSurface(true);
5277 host_impl_->active_tree()->SetRootLayer(root.Pass());
5278 EXPECT_FALSE(provider->TestContext3d()->reshape_called());
5279 provider->TestContext3d()->clear_reshape_called();
5281 LayerTreeHostImpl::FrameData frame;
5282 host_impl_->SetViewportSize(gfx::Size(10, 10));
5283 host_impl_->SetDeviceScaleFactor(1.f);
5284 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5285 host_impl_->DrawLayers(&frame);
5286 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5287 EXPECT_EQ(provider->TestContext3d()->width(), 10);
5288 EXPECT_EQ(provider->TestContext3d()->height(), 10);
5289 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5290 host_impl_->DidDrawAllLayers(frame);
5291 provider->TestContext3d()->clear_reshape_called();
5293 host_impl_->SetViewportSize(gfx::Size(20, 30));
5294 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5295 host_impl_->DrawLayers(&frame);
5296 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5297 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5298 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5299 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 1.f);
5300 host_impl_->DidDrawAllLayers(frame);
5301 provider->TestContext3d()->clear_reshape_called();
5303 host_impl_->SetDeviceScaleFactor(2.f);
5304 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5305 host_impl_->DrawLayers(&frame);
5306 EXPECT_TRUE(provider->TestContext3d()->reshape_called());
5307 EXPECT_EQ(provider->TestContext3d()->width(), 20);
5308 EXPECT_EQ(provider->TestContext3d()->height(), 30);
5309 EXPECT_EQ(provider->TestContext3d()->scale_factor(), 2.f);
5310 host_impl_->DidDrawAllLayers(frame);
5311 provider->TestContext3d()->clear_reshape_called();
5314 // Make sure damage tracking propagates all the way to the graphics context,
5315 // where it should request to swap only the sub-buffer that is damaged.
5316 TEST_F(LayerTreeHostImplTest, PartialSwapReceivesDamageRect) {
5317 scoped_refptr<TestContextProvider> context_provider(
5318 TestContextProvider::Create());
5319 context_provider->BindToCurrentThread();
5320 context_provider->TestContext3d()->set_have_post_sub_buffer(true);
5322 scoped_ptr<FakeOutputSurface> output_surface(
5323 FakeOutputSurface::Create3d(context_provider));
5324 FakeOutputSurface* fake_output_surface = output_surface.get();
5326 // This test creates its own LayerTreeHostImpl, so
5327 // that we can force partial swap enabled.
5328 LayerTreeSettings settings;
5329 settings.renderer_settings.partial_swap_enabled = true;
5330 scoped_ptr<LayerTreeHostImpl> layer_tree_host_impl =
5331 LayerTreeHostImpl::Create(
5332 settings, this, &proxy_, &stats_instrumentation_,
5333 &shared_bitmap_manager_, NULL, &task_graph_runner_, 0);
5334 layer_tree_host_impl->InitializeRenderer(output_surface.Pass());
5335 layer_tree_host_impl->WillBeginImplFrame(
5336 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5337 layer_tree_host_impl->SetViewportSize(gfx::Size(500, 500));
5339 scoped_ptr<LayerImpl> root =
5340 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 1);
5341 root->SetHasRenderSurface(true);
5342 scoped_ptr<LayerImpl> child =
5343 FakeDrawableLayerImpl::Create(layer_tree_host_impl->active_tree(), 2);
5344 child->SetPosition(gfx::PointF(12.f, 13.f));
5345 child->SetBounds(gfx::Size(14, 15));
5346 child->SetDrawsContent(true);
5347 root->SetBounds(gfx::Size(500, 500));
5348 root->SetDrawsContent(true);
5349 root->AddChild(child.Pass());
5350 layer_tree_host_impl->active_tree()->SetRootLayer(root.Pass());
5352 LayerTreeHostImpl::FrameData frame;
5354 // First frame, the entire screen should get swapped.
5355 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5356 layer_tree_host_impl->DrawLayers(&frame);
5357 layer_tree_host_impl->DidDrawAllLayers(frame);
5358 layer_tree_host_impl->SwapBuffers(frame);
5359 gfx::Rect expected_swap_rect(0, 0, 500, 500);
5360 EXPECT_EQ(expected_swap_rect.ToString(),
5361 fake_output_surface->last_swap_rect().ToString());
5363 // Second frame, only the damaged area should get swapped. Damage should be
5364 // the union of old and new child rects.
5365 // expected damage rect: gfx::Rect(26, 28);
5366 // expected swap rect: vertically flipped, with origin at bottom left corner.
5367 layer_tree_host_impl->active_tree()->root_layer()->children()[0]->SetPosition(
5368 gfx::PointF());
5369 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5370 layer_tree_host_impl->DrawLayers(&frame);
5371 host_impl_->DidDrawAllLayers(frame);
5372 layer_tree_host_impl->SwapBuffers(frame);
5374 // Make sure that partial swap is constrained to the viewport dimensions
5375 // expected damage rect: gfx::Rect(500, 500);
5376 // expected swap rect: flipped damage rect, but also clamped to viewport
5377 expected_swap_rect = gfx::Rect(0, 500-28, 26, 28);
5378 EXPECT_EQ(expected_swap_rect.ToString(),
5379 fake_output_surface->last_swap_rect().ToString());
5381 layer_tree_host_impl->SetViewportSize(gfx::Size(10, 10));
5382 // This will damage everything.
5383 layer_tree_host_impl->active_tree()->root_layer()->SetBackgroundColor(
5384 SK_ColorBLACK);
5385 EXPECT_EQ(DRAW_SUCCESS, layer_tree_host_impl->PrepareToDraw(&frame));
5386 layer_tree_host_impl->DrawLayers(&frame);
5387 host_impl_->DidDrawAllLayers(frame);
5388 layer_tree_host_impl->SwapBuffers(frame);
5390 expected_swap_rect = gfx::Rect(0, 0, 10, 10);
5391 EXPECT_EQ(expected_swap_rect.ToString(),
5392 fake_output_surface->last_swap_rect().ToString());
5395 TEST_F(LayerTreeHostImplTest, RootLayerDoesntCreateExtraSurface) {
5396 scoped_ptr<LayerImpl> root =
5397 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 1);
5398 scoped_ptr<LayerImpl> child =
5399 FakeDrawableLayerImpl::Create(host_impl_->active_tree(), 2);
5400 child->SetBounds(gfx::Size(10, 10));
5401 child->SetDrawsContent(true);
5402 root->SetBounds(gfx::Size(10, 10));
5403 root->SetDrawsContent(true);
5404 root->SetHasRenderSurface(true);
5405 root->AddChild(child.Pass());
5407 host_impl_->active_tree()->SetRootLayer(root.Pass());
5409 LayerTreeHostImpl::FrameData frame;
5411 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5412 EXPECT_EQ(1u, frame.render_surface_layer_list->size());
5413 EXPECT_EQ(1u, frame.render_passes.size());
5414 host_impl_->DidDrawAllLayers(frame);
5417 class FakeLayerWithQuads : public LayerImpl {
5418 public:
5419 static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl, int id) {
5420 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl, id));
5423 void AppendQuads(RenderPass* render_pass,
5424 AppendQuadsData* append_quads_data) override {
5425 SharedQuadState* shared_quad_state =
5426 render_pass->CreateAndAppendSharedQuadState();
5427 PopulateSharedQuadState(shared_quad_state);
5429 SkColor gray = SkColorSetRGB(100, 100, 100);
5430 gfx::Rect quad_rect(bounds());
5431 gfx::Rect visible_quad_rect(quad_rect);
5432 SolidColorDrawQuad* my_quad =
5433 render_pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
5434 my_quad->SetNew(
5435 shared_quad_state, quad_rect, visible_quad_rect, gray, false);
5438 private:
5439 FakeLayerWithQuads(LayerTreeImpl* tree_impl, int id)
5440 : LayerImpl(tree_impl, id) {}
5443 class MockContext : public TestWebGraphicsContext3D {
5444 public:
5445 MOCK_METHOD1(useProgram, void(GLuint program));
5446 MOCK_METHOD5(uniform4f, void(GLint location,
5447 GLfloat x,
5448 GLfloat y,
5449 GLfloat z,
5450 GLfloat w));
5451 MOCK_METHOD4(uniformMatrix4fv, void(GLint location,
5452 GLsizei count,
5453 GLboolean transpose,
5454 const GLfloat* value));
5455 MOCK_METHOD4(drawElements, void(GLenum mode,
5456 GLsizei count,
5457 GLenum type,
5458 GLintptr offset));
5459 MOCK_METHOD1(enable, void(GLenum cap));
5460 MOCK_METHOD1(disable, void(GLenum cap));
5461 MOCK_METHOD4(scissor, void(GLint x,
5462 GLint y,
5463 GLsizei width,
5464 GLsizei height));
5467 class MockContextHarness {
5468 private:
5469 MockContext* context_;
5471 public:
5472 explicit MockContextHarness(MockContext* context)
5473 : context_(context) {
5474 context_->set_have_post_sub_buffer(true);
5476 // Catch "uninteresting" calls
5477 EXPECT_CALL(*context_, useProgram(_))
5478 .Times(0);
5480 EXPECT_CALL(*context_, drawElements(_, _, _, _))
5481 .Times(0);
5483 // These are not asserted
5484 EXPECT_CALL(*context_, uniformMatrix4fv(_, _, _, _))
5485 .WillRepeatedly(Return());
5487 EXPECT_CALL(*context_, uniform4f(_, _, _, _, _))
5488 .WillRepeatedly(Return());
5490 // Any un-sanctioned calls to enable() are OK
5491 EXPECT_CALL(*context_, enable(_))
5492 .WillRepeatedly(Return());
5494 // Any un-sanctioned calls to disable() are OK
5495 EXPECT_CALL(*context_, disable(_))
5496 .WillRepeatedly(Return());
5499 void MustDrawSolidQuad() {
5500 EXPECT_CALL(*context_, drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0))
5501 .WillOnce(Return())
5502 .RetiresOnSaturation();
5504 EXPECT_CALL(*context_, useProgram(_))
5505 .WillOnce(Return())
5506 .RetiresOnSaturation();
5509 void MustSetScissor(int x, int y, int width, int height) {
5510 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5511 .WillRepeatedly(Return());
5513 EXPECT_CALL(*context_, scissor(x, y, width, height))
5514 .Times(AtLeast(1))
5515 .WillRepeatedly(Return());
5518 void MustSetNoScissor() {
5519 EXPECT_CALL(*context_, disable(GL_SCISSOR_TEST))
5520 .WillRepeatedly(Return());
5522 EXPECT_CALL(*context_, enable(GL_SCISSOR_TEST))
5523 .Times(0);
5525 EXPECT_CALL(*context_, scissor(_, _, _, _))
5526 .Times(0);
5530 TEST_F(LayerTreeHostImplTest, NoPartialSwap) {
5531 scoped_ptr<MockContext> mock_context_owned(new MockContext);
5532 MockContext* mock_context = mock_context_owned.get();
5533 MockContextHarness harness(mock_context);
5535 // Run test case
5536 LayerTreeSettings settings = DefaultSettings();
5537 settings.renderer_settings.partial_swap_enabled = false;
5538 CreateHostImpl(settings,
5539 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5540 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5542 // Without partial swap, and no clipping, no scissor is set.
5543 harness.MustDrawSolidQuad();
5544 harness.MustSetNoScissor();
5546 LayerTreeHostImpl::FrameData frame;
5547 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5548 host_impl_->DrawLayers(&frame);
5549 host_impl_->DidDrawAllLayers(frame);
5551 Mock::VerifyAndClearExpectations(&mock_context);
5553 // Without partial swap, but a layer does clip its subtree, one scissor is
5554 // set.
5555 host_impl_->active_tree()->root_layer()->SetMasksToBounds(true);
5556 harness.MustDrawSolidQuad();
5557 harness.MustSetScissor(0, 0, 10, 10);
5559 LayerTreeHostImpl::FrameData frame;
5560 host_impl_->active_tree()->BuildPropertyTreesForTesting();
5561 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5562 host_impl_->DrawLayers(&frame);
5563 host_impl_->DidDrawAllLayers(frame);
5565 Mock::VerifyAndClearExpectations(&mock_context);
5568 TEST_F(LayerTreeHostImplTest, PartialSwap) {
5569 scoped_ptr<MockContext> context_owned(new MockContext);
5570 MockContext* mock_context = context_owned.get();
5571 MockContextHarness harness(mock_context);
5573 LayerTreeSettings settings = DefaultSettings();
5574 settings.renderer_settings.partial_swap_enabled = true;
5575 CreateHostImpl(settings, FakeOutputSurface::Create3d(context_owned.Pass()));
5576 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
5578 // The first frame is not a partially-swapped one. No scissor should be set.
5579 harness.MustSetNoScissor();
5580 harness.MustDrawSolidQuad();
5582 LayerTreeHostImpl::FrameData frame;
5583 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5584 host_impl_->DrawLayers(&frame);
5585 host_impl_->DidDrawAllLayers(frame);
5587 Mock::VerifyAndClearExpectations(&mock_context);
5589 // Damage a portion of the frame.
5590 host_impl_->active_tree()->root_layer()->SetUpdateRect(
5591 gfx::Rect(0, 0, 2, 3));
5593 // The second frame will be partially-swapped (the y coordinates are flipped).
5594 harness.MustSetScissor(0, 7, 2, 3);
5595 harness.MustDrawSolidQuad();
5597 LayerTreeHostImpl::FrameData frame;
5598 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5599 host_impl_->DrawLayers(&frame);
5600 host_impl_->DidDrawAllLayers(frame);
5602 Mock::VerifyAndClearExpectations(&mock_context);
5605 static scoped_ptr<LayerTreeHostImpl> SetupLayersForOpacity(
5606 bool partial_swap,
5607 LayerTreeHostImplClient* client,
5608 Proxy* proxy,
5609 SharedBitmapManager* manager,
5610 TaskGraphRunner* task_graph_runner,
5611 RenderingStatsInstrumentation* stats_instrumentation) {
5612 scoped_refptr<TestContextProvider> provider(TestContextProvider::Create());
5613 scoped_ptr<OutputSurface> output_surface(
5614 FakeOutputSurface::Create3d(provider));
5615 provider->BindToCurrentThread();
5616 provider->TestContext3d()->set_have_post_sub_buffer(true);
5618 LayerTreeSettings settings;
5619 settings.renderer_settings.partial_swap_enabled = partial_swap;
5620 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5621 LayerTreeHostImpl::Create(settings, client, proxy, stats_instrumentation,
5622 manager, nullptr, task_graph_runner, 0);
5623 my_host_impl->InitializeRenderer(output_surface.Pass());
5624 my_host_impl->WillBeginImplFrame(
5625 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE));
5626 my_host_impl->SetViewportSize(gfx::Size(100, 100));
5629 Layers are created as follows:
5631 +--------------------+
5632 | 1 |
5633 | +-----------+ |
5634 | | 2 | |
5635 | | +-------------------+
5636 | | | 3 |
5637 | | +-------------------+
5638 | | | |
5639 | +-----------+ |
5642 +--------------------+
5644 Layers 1, 2 have render surfaces
5646 scoped_ptr<LayerImpl> root =
5647 LayerImpl::Create(my_host_impl->active_tree(), 1);
5648 scoped_ptr<LayerImpl> child =
5649 LayerImpl::Create(my_host_impl->active_tree(), 2);
5650 scoped_ptr<LayerImpl> grand_child =
5651 FakeLayerWithQuads::Create(my_host_impl->active_tree(), 3);
5653 gfx::Rect root_rect(0, 0, 100, 100);
5654 gfx::Rect child_rect(10, 10, 50, 50);
5655 gfx::Rect grand_child_rect(5, 5, 150, 150);
5657 root->SetHasRenderSurface(true);
5658 root->SetPosition(root_rect.origin());
5659 root->SetBounds(root_rect.size());
5660 root->draw_properties().visible_layer_rect = root_rect;
5661 root->SetDrawsContent(false);
5662 root->render_surface()->SetContentRect(gfx::Rect(root_rect.size()));
5664 child->SetPosition(gfx::PointF(child_rect.x(), child_rect.y()));
5665 child->SetOpacity(0.5f);
5666 child->SetBounds(gfx::Size(child_rect.width(), child_rect.height()));
5667 child->draw_properties().visible_layer_rect = child_rect;
5668 child->SetDrawsContent(false);
5669 child->SetHasRenderSurface(true);
5671 grand_child->SetPosition(grand_child_rect.origin());
5672 grand_child->SetBounds(grand_child_rect.size());
5673 grand_child->draw_properties().visible_layer_rect = grand_child_rect;
5674 grand_child->SetDrawsContent(true);
5676 child->AddChild(grand_child.Pass());
5677 root->AddChild(child.Pass());
5679 my_host_impl->active_tree()->SetRootLayer(root.Pass());
5680 return my_host_impl.Pass();
5683 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorPartialSwap) {
5684 TestSharedBitmapManager shared_bitmap_manager;
5685 TestTaskGraphRunner task_graph_runner;
5686 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5687 SetupLayersForOpacity(true, this, &proxy_, &shared_bitmap_manager,
5688 &task_graph_runner, &stats_instrumentation_);
5690 LayerTreeHostImpl::FrameData frame;
5691 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5693 // Verify all quads have been computed
5694 ASSERT_EQ(2U, frame.render_passes.size());
5695 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5696 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5697 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5698 frame.render_passes[0]->quad_list.front()->material);
5699 EXPECT_EQ(DrawQuad::RENDER_PASS,
5700 frame.render_passes[1]->quad_list.front()->material);
5702 my_host_impl->DrawLayers(&frame);
5703 my_host_impl->DidDrawAllLayers(frame);
5707 TEST_F(LayerTreeHostImplTest, ContributingLayerEmptyScissorNoPartialSwap) {
5708 TestSharedBitmapManager shared_bitmap_manager;
5709 TestTaskGraphRunner task_graph_runner;
5710 scoped_ptr<LayerTreeHostImpl> my_host_impl =
5711 SetupLayersForOpacity(false, this, &proxy_, &shared_bitmap_manager,
5712 &task_graph_runner, &stats_instrumentation_);
5714 LayerTreeHostImpl::FrameData frame;
5715 EXPECT_EQ(DRAW_SUCCESS, my_host_impl->PrepareToDraw(&frame));
5717 // Verify all quads have been computed
5718 ASSERT_EQ(2U, frame.render_passes.size());
5719 ASSERT_EQ(1U, frame.render_passes[0]->quad_list.size());
5720 ASSERT_EQ(1U, frame.render_passes[1]->quad_list.size());
5721 EXPECT_EQ(DrawQuad::SOLID_COLOR,
5722 frame.render_passes[0]->quad_list.front()->material);
5723 EXPECT_EQ(DrawQuad::RENDER_PASS,
5724 frame.render_passes[1]->quad_list.front()->material);
5726 my_host_impl->DrawLayers(&frame);
5727 my_host_impl->DidDrawAllLayers(frame);
5731 TEST_F(LayerTreeHostImplTest, LayersFreeTextures) {
5732 scoped_ptr<TestWebGraphicsContext3D> context =
5733 TestWebGraphicsContext3D::Create();
5734 TestWebGraphicsContext3D* context3d = context.get();
5735 scoped_ptr<OutputSurface> output_surface(
5736 FakeOutputSurface::Create3d(context.Pass()));
5737 CreateHostImpl(DefaultSettings(), output_surface.Pass());
5739 scoped_ptr<LayerImpl> root_layer =
5740 LayerImpl::Create(host_impl_->active_tree(), 1);
5741 root_layer->SetBounds(gfx::Size(10, 10));
5742 root_layer->SetHasRenderSurface(true);
5744 scoped_refptr<VideoFrame> softwareFrame =
5745 media::VideoFrame::CreateColorFrame(
5746 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5747 FakeVideoFrameProvider provider;
5748 provider.set_frame(softwareFrame);
5749 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
5750 host_impl_->active_tree(), 4, &provider, media::VIDEO_ROTATION_0);
5751 video_layer->SetBounds(gfx::Size(10, 10));
5752 video_layer->SetDrawsContent(true);
5753 root_layer->AddChild(video_layer.Pass());
5755 scoped_ptr<IOSurfaceLayerImpl> io_surface_layer =
5756 IOSurfaceLayerImpl::Create(host_impl_->active_tree(), 5);
5757 io_surface_layer->SetBounds(gfx::Size(10, 10));
5758 io_surface_layer->SetDrawsContent(true);
5759 io_surface_layer->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5760 root_layer->AddChild(io_surface_layer.Pass());
5762 host_impl_->active_tree()->SetRootLayer(root_layer.Pass());
5764 EXPECT_EQ(0u, context3d->NumTextures());
5766 LayerTreeHostImpl::FrameData frame;
5767 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5768 host_impl_->DrawLayers(&frame);
5769 host_impl_->DidDrawAllLayers(frame);
5770 host_impl_->SwapBuffers(frame);
5772 EXPECT_GT(context3d->NumTextures(), 0u);
5774 // Kill the layer tree.
5775 host_impl_->active_tree()->SetRootLayer(
5776 LayerImpl::Create(host_impl_->active_tree(), 100));
5777 // There should be no textures left in use after.
5778 EXPECT_EQ(0u, context3d->NumTextures());
5781 class MockDrawQuadsToFillScreenContext : public TestWebGraphicsContext3D {
5782 public:
5783 MOCK_METHOD1(useProgram, void(GLuint program));
5784 MOCK_METHOD4(drawElements, void(GLenum mode,
5785 GLsizei count,
5786 GLenum type,
5787 GLintptr offset));
5790 TEST_F(LayerTreeHostImplTest, HasTransparentBackground) {
5791 scoped_ptr<MockDrawQuadsToFillScreenContext> mock_context_owned(
5792 new MockDrawQuadsToFillScreenContext);
5793 MockDrawQuadsToFillScreenContext* mock_context = mock_context_owned.get();
5795 // Run test case
5796 LayerTreeSettings settings = DefaultSettings();
5797 settings.renderer_settings.partial_swap_enabled = false;
5798 CreateHostImpl(settings,
5799 FakeOutputSurface::Create3d(mock_context_owned.Pass()));
5800 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
5801 host_impl_->active_tree()->set_background_color(SK_ColorWHITE);
5803 // Verify one quad is drawn when transparent background set is not set.
5804 host_impl_->active_tree()->set_has_transparent_background(false);
5805 EXPECT_CALL(*mock_context, useProgram(_))
5806 .Times(1);
5807 EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
5808 .Times(1);
5809 LayerTreeHostImpl::FrameData frame;
5810 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5811 host_impl_->DrawLayers(&frame);
5812 host_impl_->DidDrawAllLayers(frame);
5813 Mock::VerifyAndClearExpectations(&mock_context);
5815 // Verify no quads are drawn when transparent background is set.
5816 host_impl_->active_tree()->set_has_transparent_background(true);
5817 host_impl_->SetFullRootLayerDamage();
5818 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5819 host_impl_->DrawLayers(&frame);
5820 host_impl_->DidDrawAllLayers(frame);
5821 Mock::VerifyAndClearExpectations(&mock_context);
5824 class LayerTreeHostImplTestWithDelegatingRenderer
5825 : public LayerTreeHostImplTest {
5826 protected:
5827 scoped_ptr<OutputSurface> CreateOutputSurface() override {
5828 return FakeOutputSurface::CreateDelegating3d();
5831 void DrawFrameAndTestDamage(const gfx::RectF& expected_damage) {
5832 bool expect_to_draw = !expected_damage.IsEmpty();
5834 LayerTreeHostImpl::FrameData frame;
5835 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5837 if (!expect_to_draw) {
5838 // With no damage, we don't draw, and no quads are created.
5839 ASSERT_EQ(0u, frame.render_passes.size());
5840 } else {
5841 ASSERT_EQ(1u, frame.render_passes.size());
5843 // Verify the damage rect for the root render pass.
5844 const RenderPass* root_render_pass = frame.render_passes.back();
5845 EXPECT_EQ(expected_damage, root_render_pass->damage_rect);
5847 // Verify the root and child layers' quads are generated and not being
5848 // culled.
5849 ASSERT_EQ(2u, root_render_pass->quad_list.size());
5851 LayerImpl* child = host_impl_->active_tree()->root_layer()->children()[0];
5852 gfx::RectF expected_child_visible_rect(child->bounds());
5853 EXPECT_EQ(expected_child_visible_rect,
5854 root_render_pass->quad_list.front()->visible_rect);
5856 LayerImpl* root = host_impl_->active_tree()->root_layer();
5857 gfx::RectF expected_root_visible_rect(root->bounds());
5858 EXPECT_EQ(expected_root_visible_rect,
5859 root_render_pass->quad_list.ElementAt(1)->visible_rect);
5862 host_impl_->DrawLayers(&frame);
5863 host_impl_->DidDrawAllLayers(frame);
5864 EXPECT_EQ(expect_to_draw, host_impl_->SwapBuffers(frame));
5868 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, FrameIncludesDamageRect) {
5869 scoped_ptr<SolidColorLayerImpl> root =
5870 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
5871 root->SetPosition(gfx::PointF());
5872 root->SetBounds(gfx::Size(10, 10));
5873 root->SetDrawsContent(true);
5874 root->SetHasRenderSurface(true);
5876 // Child layer is in the bottom right corner.
5877 scoped_ptr<SolidColorLayerImpl> child =
5878 SolidColorLayerImpl::Create(host_impl_->active_tree(), 2);
5879 child->SetPosition(gfx::PointF(9.f, 9.f));
5880 child->SetBounds(gfx::Size(1, 1));
5881 child->SetDrawsContent(true);
5882 root->AddChild(child.Pass());
5884 host_impl_->active_tree()->SetRootLayer(root.Pass());
5886 // Draw a frame. In the first frame, the entire viewport should be damaged.
5887 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
5888 DrawFrameAndTestDamage(full_frame_damage);
5890 // The second frame has damage that doesn't touch the child layer. Its quads
5891 // should still be generated.
5892 gfx::Rect small_damage = gfx::Rect(0, 0, 1, 1);
5893 host_impl_->active_tree()->root_layer()->SetUpdateRect(small_damage);
5894 DrawFrameAndTestDamage(small_damage);
5896 // The third frame should have no damage, so no quads should be generated.
5897 gfx::Rect no_damage;
5898 DrawFrameAndTestDamage(no_damage);
5901 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5902 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5903 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer, PreventRasterizeOnDemand) {
5904 LayerTreeSettings settings;
5905 CreateHostImpl(settings, CreateOutputSurface());
5906 EXPECT_FALSE(host_impl_->GetRendererCapabilities().allow_rasterize_on_demand);
5909 class FakeMaskLayerImpl : public LayerImpl {
5910 public:
5911 static scoped_ptr<FakeMaskLayerImpl> Create(LayerTreeImpl* tree_impl,
5912 int id) {
5913 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl, id));
5916 void GetContentsResourceId(ResourceId* resource_id,
5917 gfx::Size* resource_size) const override {
5918 *resource_id = 0;
5921 private:
5922 FakeMaskLayerImpl(LayerTreeImpl* tree_impl, int id)
5923 : LayerImpl(tree_impl, id) {}
5926 class GLRendererWithSetupQuadForAntialiasing : public GLRenderer {
5927 public:
5928 using GLRenderer::ShouldAntialiasQuad;
5931 TEST_F(LayerTreeHostImplTest, FarAwayQuadsDontNeedAA) {
5932 // Due to precision issues (especially on Android), sometimes far
5933 // away quads can end up thinking they need AA.
5934 float device_scale_factor = 4.f / 3.f;
5935 host_impl_->SetDeviceScaleFactor(device_scale_factor);
5936 gfx::Size root_size(2000, 1000);
5937 gfx::Size device_viewport_size =
5938 gfx::ToCeiledSize(gfx::ScaleSize(root_size, device_scale_factor));
5939 host_impl_->SetViewportSize(device_viewport_size);
5941 host_impl_->CreatePendingTree();
5942 host_impl_->pending_tree()->PushPageScaleFromMainThread(1.f, 1.f / 16.f,
5943 16.f);
5945 scoped_ptr<LayerImpl> scoped_root =
5946 LayerImpl::Create(host_impl_->pending_tree(), 1);
5947 LayerImpl* root = scoped_root.get();
5948 root->SetHasRenderSurface(true);
5950 host_impl_->pending_tree()->SetRootLayer(scoped_root.Pass());
5952 scoped_ptr<LayerImpl> scoped_scrolling_layer =
5953 LayerImpl::Create(host_impl_->pending_tree(), 2);
5954 LayerImpl* scrolling_layer = scoped_scrolling_layer.get();
5955 root->AddChild(scoped_scrolling_layer.Pass());
5957 gfx::Size content_layer_bounds(100000, 100);
5958 gfx::Size pile_tile_size(3000, 3000);
5959 scoped_refptr<FakePicturePileImpl> pile(FakePicturePileImpl::CreateFilledPile(
5960 pile_tile_size, content_layer_bounds));
5962 scoped_ptr<FakePictureLayerImpl> scoped_content_layer =
5963 FakePictureLayerImpl::CreateWithRasterSource(host_impl_->pending_tree(),
5964 3, pile);
5965 LayerImpl* content_layer = scoped_content_layer.get();
5966 scrolling_layer->AddChild(scoped_content_layer.Pass());
5967 content_layer->SetBounds(content_layer_bounds);
5968 content_layer->SetDrawsContent(true);
5970 root->SetBounds(root_size);
5972 gfx::ScrollOffset scroll_offset(100000, 0);
5973 scrolling_layer->SetScrollClipLayer(root->id());
5974 scrolling_layer->PushScrollOffsetFromMainThread(scroll_offset);
5976 host_impl_->ActivateSyncTree();
5978 bool update_lcd_text = false;
5979 host_impl_->active_tree()->UpdateDrawProperties(update_lcd_text);
5980 ASSERT_EQ(1u, host_impl_->active_tree()->RenderSurfaceLayerList().size());
5982 LayerTreeHostImpl::FrameData frame;
5983 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
5985 ASSERT_EQ(1u, frame.render_passes.size());
5986 ASSERT_LE(1u, frame.render_passes[0]->quad_list.size());
5987 const DrawQuad* quad = frame.render_passes[0]->quad_list.front();
5989 bool clipped = false, force_aa = false;
5990 gfx::QuadF device_layer_quad = MathUtil::MapQuad(
5991 quad->shared_quad_state->quad_to_target_transform,
5992 gfx::QuadF(quad->shared_quad_state->visible_quad_layer_rect), &clipped);
5993 EXPECT_FALSE(clipped);
5994 bool antialiased =
5995 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
5996 device_layer_quad, clipped, force_aa);
5997 EXPECT_FALSE(antialiased);
5999 host_impl_->DrawLayers(&frame);
6000 host_impl_->DidDrawAllLayers(frame);
6004 class CompositorFrameMetadataTest : public LayerTreeHostImplTest {
6005 public:
6006 CompositorFrameMetadataTest()
6007 : swap_buffers_complete_(0) {}
6009 void DidSwapBuffersCompleteOnImplThread() override {
6010 swap_buffers_complete_++;
6013 int swap_buffers_complete_;
6016 TEST_F(CompositorFrameMetadataTest, CompositorFrameAckCountsAsSwapComplete) {
6017 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_->active_tree(), 1));
6019 LayerTreeHostImpl::FrameData frame;
6020 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6021 host_impl_->DrawLayers(&frame);
6022 host_impl_->DidDrawAllLayers(frame);
6024 CompositorFrameAck ack;
6025 host_impl_->ReclaimResources(&ack);
6026 host_impl_->DidSwapBuffersComplete();
6027 EXPECT_EQ(swap_buffers_complete_, 1);
6030 class CountingSoftwareDevice : public SoftwareOutputDevice {
6031 public:
6032 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6034 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
6035 ++frames_began_;
6036 return SoftwareOutputDevice::BeginPaint(damage_rect);
6038 void EndPaint() override {
6039 SoftwareOutputDevice::EndPaint();
6040 ++frames_ended_;
6043 int frames_began_, frames_ended_;
6046 TEST_F(LayerTreeHostImplTest, ForcedDrawToSoftwareDeviceBasicRender) {
6047 // No main thread evictions in resourceless software mode.
6048 set_reduce_memory_result(false);
6049 CountingSoftwareDevice* software_device = new CountingSoftwareDevice();
6050 EXPECT_TRUE(CreateHostImpl(
6051 DefaultSettings(),
6052 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device))));
6053 host_impl_->SetViewportSize(gfx::Size(50, 50));
6055 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6057 const gfx::Transform external_transform;
6058 const gfx::Rect external_viewport;
6059 const gfx::Rect external_clip;
6060 const bool resourceless_software_draw = true;
6061 host_impl_->SetExternalDrawConstraints(external_transform,
6062 external_viewport,
6063 external_clip,
6064 external_viewport,
6065 external_transform,
6066 resourceless_software_draw);
6068 EXPECT_EQ(0, software_device->frames_began_);
6069 EXPECT_EQ(0, software_device->frames_ended_);
6071 DrawFrame();
6073 EXPECT_EQ(1, software_device->frames_began_);
6074 EXPECT_EQ(1, software_device->frames_ended_);
6076 // Call another API method that is likely to hit nullptr in this mode.
6077 scoped_refptr<base::trace_event::TracedValue> state =
6078 make_scoped_refptr(new base::trace_event::TracedValue());
6079 host_impl_->ActivationStateAsValueInto(state.get());
6082 TEST_F(LayerTreeHostImplTest,
6083 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers) {
6084 set_reduce_memory_result(false);
6085 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6086 FakeOutputSurface::CreateSoftware(
6087 make_scoped_ptr(new CountingSoftwareDevice))));
6089 const gfx::Transform external_transform;
6090 const gfx::Rect external_viewport;
6091 const gfx::Rect external_clip;
6092 const bool resourceless_software_draw = true;
6093 host_impl_->SetExternalDrawConstraints(external_transform,
6094 external_viewport,
6095 external_clip,
6096 external_viewport,
6097 external_transform,
6098 resourceless_software_draw);
6100 // SolidColorLayerImpl will be drawn.
6101 scoped_ptr<SolidColorLayerImpl> root_layer =
6102 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6104 // VideoLayerImpl will not be drawn.
6105 FakeVideoFrameProvider provider;
6106 scoped_ptr<VideoLayerImpl> video_layer = VideoLayerImpl::Create(
6107 host_impl_->active_tree(), 2, &provider, media::VIDEO_ROTATION_0);
6108 video_layer->SetBounds(gfx::Size(10, 10));
6109 video_layer->SetDrawsContent(true);
6110 root_layer->AddChild(video_layer.Pass());
6111 SetupRootLayerImpl(root_layer.Pass());
6113 LayerTreeHostImpl::FrameData frame;
6114 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6115 host_impl_->DrawLayers(&frame);
6116 host_impl_->DidDrawAllLayers(frame);
6118 EXPECT_EQ(1u, frame.will_draw_layers.size());
6119 EXPECT_EQ(host_impl_->active_tree()->root_layer(), frame.will_draw_layers[0]);
6122 // Checks that we have a non-0 default allocation if we pass a context that
6123 // doesn't support memory management extensions.
6124 TEST_F(LayerTreeHostImplTest, DefaultMemoryAllocation) {
6125 LayerTreeSettings settings;
6126 host_impl_ = LayerTreeHostImpl::Create(
6127 settings, this, &proxy_, &stats_instrumentation_, &shared_bitmap_manager_,
6128 &gpu_memory_buffer_manager_, &task_graph_runner_, 0);
6130 scoped_ptr<OutputSurface> output_surface(
6131 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6132 host_impl_->InitializeRenderer(output_surface.Pass());
6133 EXPECT_LT(0ul, host_impl_->memory_allocation_limit_bytes());
6136 TEST_F(LayerTreeHostImplTest, RequireHighResWhenVisible) {
6137 ASSERT_TRUE(host_impl_->active_tree());
6139 // RequiresHighResToDraw is set when new output surface is used.
6140 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6142 host_impl_->ResetRequiresHighResToDraw();
6144 host_impl_->SetVisible(false);
6145 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6146 host_impl_->SetVisible(true);
6147 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6148 host_impl_->SetVisible(false);
6149 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6151 host_impl_->ResetRequiresHighResToDraw();
6153 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6154 host_impl_->SetVisible(true);
6155 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6158 TEST_F(LayerTreeHostImplTest, RequireHighResAfterGpuRasterizationToggles) {
6159 ASSERT_TRUE(host_impl_->active_tree());
6160 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
6162 // RequiresHighResToDraw is set when new output surface is used.
6163 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6165 host_impl_->ResetRequiresHighResToDraw();
6167 host_impl_->SetContentIsSuitableForGpuRasterization(true);
6168 host_impl_->SetHasGpuRasterizationTrigger(false);
6169 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6170 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6171 host_impl_->SetHasGpuRasterizationTrigger(true);
6172 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6173 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6174 host_impl_->SetHasGpuRasterizationTrigger(false);
6175 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6176 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6178 host_impl_->ResetRequiresHighResToDraw();
6180 EXPECT_FALSE(host_impl_->RequiresHighResToDraw());
6181 host_impl_->SetHasGpuRasterizationTrigger(true);
6182 host_impl_->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6183 EXPECT_TRUE(host_impl_->RequiresHighResToDraw());
6186 class LayerTreeHostImplTestPrepareTiles : public LayerTreeHostImplTest {
6187 public:
6188 void SetUp() override {
6189 fake_host_impl_ =
6190 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_,
6191 &shared_bitmap_manager_, &task_graph_runner_);
6192 host_impl_.reset(fake_host_impl_);
6193 host_impl_->InitializeRenderer(CreateOutputSurface());
6194 host_impl_->SetViewportSize(gfx::Size(10, 10));
6197 FakeLayerTreeHostImpl* fake_host_impl_;
6200 TEST_F(LayerTreeHostImplTestPrepareTiles, PrepareTilesWhenInvisible) {
6201 fake_host_impl_->DidModifyTilePriorities();
6202 EXPECT_TRUE(fake_host_impl_->prepare_tiles_needed());
6203 fake_host_impl_->SetVisible(false);
6204 EXPECT_FALSE(fake_host_impl_->prepare_tiles_needed());
6207 TEST_F(LayerTreeHostImplTest, UIResourceManagement) {
6208 scoped_ptr<TestWebGraphicsContext3D> context =
6209 TestWebGraphicsContext3D::Create();
6210 TestWebGraphicsContext3D* context3d = context.get();
6211 scoped_ptr<FakeOutputSurface> output_surface = FakeOutputSurface::Create3d();
6212 CreateHostImpl(DefaultSettings(), output_surface.Pass());
6214 EXPECT_EQ(0u, context3d->NumTextures());
6216 UIResourceId ui_resource_id = 1;
6217 bool is_opaque = false;
6218 UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
6219 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6220 EXPECT_EQ(1u, context3d->NumTextures());
6221 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6222 EXPECT_NE(0u, id1);
6224 // Multiple requests with the same id is allowed. The previous texture is
6225 // deleted.
6226 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6227 EXPECT_EQ(1u, context3d->NumTextures());
6228 ResourceId id2 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6229 EXPECT_NE(0u, id2);
6230 EXPECT_NE(id1, id2);
6232 // Deleting invalid UIResourceId is allowed and does not change state.
6233 host_impl_->DeleteUIResource(-1);
6234 EXPECT_EQ(1u, context3d->NumTextures());
6236 // Should return zero for invalid UIResourceId. Number of textures should
6237 // not change.
6238 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(-1));
6239 EXPECT_EQ(1u, context3d->NumTextures());
6241 host_impl_->DeleteUIResource(ui_resource_id);
6242 EXPECT_EQ(0u, host_impl_->ResourceIdForUIResource(ui_resource_id));
6243 EXPECT_EQ(0u, context3d->NumTextures());
6245 // Should not change state for multiple deletion on one UIResourceId
6246 host_impl_->DeleteUIResource(ui_resource_id);
6247 EXPECT_EQ(0u, context3d->NumTextures());
6250 TEST_F(LayerTreeHostImplTest, CreateETC1UIResource) {
6251 scoped_ptr<TestWebGraphicsContext3D> context =
6252 TestWebGraphicsContext3D::Create();
6253 TestWebGraphicsContext3D* context3d = context.get();
6254 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6256 EXPECT_EQ(0u, context3d->NumTextures());
6258 gfx::Size size(4, 4);
6259 // SkImageInfo has no support for ETC1. The |info| below contains the right
6260 // total pixel size for the bitmap but not the right height and width. The
6261 // correct width/height are passed directly to UIResourceBitmap.
6262 SkImageInfo info =
6263 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType, kPremul_SkAlphaType);
6264 skia::RefPtr<SkPixelRef> pixel_ref =
6265 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info, 0, 0));
6266 pixel_ref->setImmutable();
6267 UIResourceBitmap bitmap(pixel_ref, size);
6268 UIResourceId ui_resource_id = 1;
6269 host_impl_->CreateUIResource(ui_resource_id, bitmap);
6270 EXPECT_EQ(1u, context3d->NumTextures());
6271 ResourceId id1 = host_impl_->ResourceIdForUIResource(ui_resource_id);
6272 EXPECT_NE(0u, id1);
6275 void ShutdownReleasesContext_Callback(scoped_ptr<CopyOutputResult> result) {
6278 TEST_F(LayerTreeHostImplTest, ShutdownReleasesContext) {
6279 scoped_refptr<TestContextProvider> context_provider =
6280 TestContextProvider::Create();
6282 CreateHostImpl(DefaultSettings(),
6283 FakeOutputSurface::Create3d(context_provider));
6285 SetupRootLayerImpl(LayerImpl::Create(host_impl_->active_tree(), 1));
6287 ScopedPtrVector<CopyOutputRequest> requests;
6288 requests.push_back(CopyOutputRequest::CreateRequest(
6289 base::Bind(&ShutdownReleasesContext_Callback)));
6291 host_impl_->active_tree()->root_layer()->PassCopyRequests(&requests);
6293 LayerTreeHostImpl::FrameData frame;
6294 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6295 host_impl_->DrawLayers(&frame);
6296 host_impl_->DidDrawAllLayers(frame);
6298 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6299 // texture in a texture mailbox.
6300 EXPECT_FALSE(context_provider->HasOneRef());
6301 EXPECT_EQ(1u, context_provider->TestContext3d()->NumTextures());
6303 host_impl_ = nullptr;
6305 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6306 // released, and the texture deleted.
6307 EXPECT_TRUE(context_provider->HasOneRef());
6308 EXPECT_EQ(0u, context_provider->TestContext3d()->NumTextures());
6311 TEST_F(LayerTreeHostImplTest, TouchFlingShouldNotBubble) {
6312 // When flinging via touch, only the child should scroll (we should not
6313 // bubble).
6314 gfx::Size surface_size(10, 10);
6315 gfx::Size content_size(20, 20);
6316 scoped_ptr<LayerImpl> root_clip =
6317 LayerImpl::Create(host_impl_->active_tree(), 3);
6318 root_clip->SetHasRenderSurface(true);
6320 scoped_ptr<LayerImpl> root =
6321 CreateScrollableLayer(1, content_size, root_clip.get());
6322 root->SetIsContainerForFixedPositionLayers(true);
6323 scoped_ptr<LayerImpl> child =
6324 CreateScrollableLayer(2, content_size, root_clip.get());
6326 root->AddChild(child.Pass());
6327 int root_id = root->id();
6328 root_clip->AddChild(root.Pass());
6330 host_impl_->SetViewportSize(surface_size);
6331 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6332 host_impl_->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID, 3, 1,
6333 Layer::INVALID_ID);
6334 host_impl_->active_tree()->DidBecomeActive();
6335 DrawFrame();
6337 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6338 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6340 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6342 gfx::Vector2d scroll_delta(0, 100);
6343 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6344 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6346 host_impl_->ScrollEnd();
6348 scoped_ptr<ScrollAndScaleSet> scroll_info =
6349 host_impl_->ProcessScrollDeltas();
6351 // Only the child should have scrolled.
6352 ASSERT_EQ(1u, scroll_info->scrolls.size());
6353 ExpectNone(*scroll_info.get(), root_id);
6357 TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) {
6358 // Scroll a child layer beyond its maximum scroll range and make sure the
6359 // the scroll doesn't bubble up to the parent layer.
6360 gfx::Size surface_size(10, 10);
6361 scoped_ptr<LayerImpl> root = LayerImpl::Create(host_impl_->active_tree(), 1);
6362 root->SetHasRenderSurface(true);
6363 scoped_ptr<LayerImpl> root_scrolling =
6364 CreateScrollableLayer(2, surface_size, root.get());
6366 scoped_ptr<LayerImpl> grand_child =
6367 CreateScrollableLayer(4, surface_size, root.get());
6368 grand_child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6370 scoped_ptr<LayerImpl> child =
6371 CreateScrollableLayer(3, surface_size, root.get());
6372 child->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6373 child->AddChild(grand_child.Pass());
6375 root_scrolling->AddChild(child.Pass());
6376 root->AddChild(root_scrolling.Pass());
6377 host_impl_->active_tree()->SetRootLayer(root.Pass());
6378 host_impl_->active_tree()->DidBecomeActive();
6379 host_impl_->SetViewportSize(surface_size);
6380 DrawFrame();
6382 scoped_ptr<ScrollAndScaleSet> scroll_info;
6383 LayerImpl* child =
6384 host_impl_->active_tree()->root_layer()->children()[0]->children()[0];
6385 LayerImpl* grand_child = child->children()[0];
6387 gfx::Vector2d scroll_delta(0, -2);
6388 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6389 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6390 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6392 // The grand child should have scrolled up to its limit.
6393 scroll_info = host_impl_->ProcessScrollDeltas();
6394 ASSERT_EQ(1u, scroll_info->scrolls.size());
6395 EXPECT_TRUE(
6396 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6397 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6399 // The child should have received the bubbled delta, but the locked
6400 // scrolling layer should remain set as the grand child.
6401 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6402 scroll_info = host_impl_->ProcessScrollDeltas();
6403 ASSERT_EQ(2u, scroll_info->scrolls.size());
6404 EXPECT_TRUE(
6405 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6406 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(), scroll_delta));
6407 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), grand_child);
6409 // The first |ScrollBy| after the fling should re-lock the scrolling
6410 // layer to the first layer that scrolled, which is the child.
6411 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6412 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6413 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6415 // The child should have scrolled up to its limit.
6416 scroll_info = host_impl_->ProcessScrollDeltas();
6417 ASSERT_EQ(2u, scroll_info->scrolls.size());
6418 EXPECT_TRUE(
6419 ScrollInfoContains(*scroll_info, grand_child->id(), scroll_delta));
6420 EXPECT_TRUE(ScrollInfoContains(*scroll_info, child->id(),
6421 scroll_delta + scroll_delta));
6423 // As the locked layer is at it's limit, no further scrolling can occur.
6424 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
6425 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child);
6426 host_impl_->ScrollEnd();
6430 TEST_F(LayerTreeHostImplTest, WheelFlingShouldBubble) {
6431 // When flinging via wheel, the root should eventually scroll (we should
6432 // bubble).
6433 gfx::Size surface_size(10, 10);
6434 gfx::Size content_size(20, 20);
6435 scoped_ptr<LayerImpl> root_clip =
6436 LayerImpl::Create(host_impl_->active_tree(), 3);
6437 root_clip->SetHasRenderSurface(true);
6438 scoped_ptr<LayerImpl> root_scroll =
6439 CreateScrollableLayer(1, content_size, root_clip.get());
6440 int root_scroll_id = root_scroll->id();
6441 scoped_ptr<LayerImpl> child =
6442 CreateScrollableLayer(2, content_size, root_clip.get());
6444 root_scroll->AddChild(child.Pass());
6445 root_clip->AddChild(root_scroll.Pass());
6447 host_impl_->SetViewportSize(surface_size);
6448 host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
6449 host_impl_->active_tree()->DidBecomeActive();
6450 DrawFrame();
6452 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6453 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6455 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
6457 gfx::Vector2d scroll_delta(0, 100);
6458 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6459 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
6461 host_impl_->ScrollEnd();
6463 scoped_ptr<ScrollAndScaleSet> scroll_info =
6464 host_impl_->ProcessScrollDeltas();
6466 // The root should have scrolled.
6467 ASSERT_EQ(2u, scroll_info->scrolls.size());
6468 EXPECT_TRUE(ScrollInfoContains(*scroll_info.get(), root_scroll_id,
6469 gfx::Vector2d(0, 10)));
6473 TEST_F(LayerTreeHostImplTest, ScrollUnknownNotOnAncestorChain) {
6474 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6475 // we should return SCROLL_UNKNOWN.
6476 gfx::Size content_size(100, 100);
6477 SetupScrollAndContentsLayers(content_size);
6479 int scroll_layer_id = 2;
6480 LayerImpl* scroll_layer =
6481 host_impl_->active_tree()->LayerById(scroll_layer_id);
6482 scroll_layer->SetDrawsContent(true);
6484 int page_scale_layer_id = 5;
6485 LayerImpl* page_scale_layer =
6486 host_impl_->active_tree()->LayerById(page_scale_layer_id);
6488 int occluder_layer_id = 6;
6489 scoped_ptr<LayerImpl> occluder_layer =
6490 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6491 occluder_layer->SetDrawsContent(true);
6492 occluder_layer->SetBounds(content_size);
6493 occluder_layer->SetPosition(gfx::PointF());
6495 // The parent of the occluder is *above* the scroller.
6496 page_scale_layer->AddChild(occluder_layer.Pass());
6498 DrawFrame();
6500 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6501 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6504 TEST_F(LayerTreeHostImplTest, ScrollUnknownScrollAncestorMismatch) {
6505 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6506 // is not the first scroller we encounter when walking up from the layer, we
6507 // should also return SCROLL_UNKNOWN.
6508 gfx::Size content_size(100, 100);
6509 SetupScrollAndContentsLayers(content_size);
6511 int scroll_layer_id = 2;
6512 LayerImpl* scroll_layer =
6513 host_impl_->active_tree()->LayerById(scroll_layer_id);
6514 scroll_layer->SetDrawsContent(true);
6516 int occluder_layer_id = 6;
6517 scoped_ptr<LayerImpl> occluder_layer =
6518 LayerImpl::Create(host_impl_->active_tree(), occluder_layer_id);
6519 occluder_layer->SetDrawsContent(true);
6520 occluder_layer->SetBounds(content_size);
6521 occluder_layer->SetPosition(gfx::PointF(-10.f, -10.f));
6523 int child_scroll_clip_layer_id = 7;
6524 scoped_ptr<LayerImpl> child_scroll_clip =
6525 LayerImpl::Create(host_impl_->active_tree(), child_scroll_clip_layer_id);
6527 int child_scroll_layer_id = 8;
6528 scoped_ptr<LayerImpl> child_scroll = CreateScrollableLayer(
6529 child_scroll_layer_id, content_size, child_scroll_clip.get());
6531 child_scroll->SetPosition(gfx::PointF(10.f, 10.f));
6533 child_scroll->AddChild(occluder_layer.Pass());
6534 scroll_layer->AddChild(child_scroll.Pass());
6536 DrawFrame();
6538 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN,
6539 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6542 TEST_F(LayerTreeHostImplTest, NotScrollInvisibleScroller) {
6543 gfx::Size content_size(100, 100);
6544 SetupScrollAndContentsLayers(content_size);
6546 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6548 int scroll_layer_id = 2;
6549 LayerImpl* scroll_layer =
6550 host_impl_->active_tree()->LayerById(scroll_layer_id);
6552 int child_scroll_layer_id = 7;
6553 scoped_ptr<LayerImpl> child_scroll =
6554 CreateScrollableLayer(child_scroll_layer_id, content_size, root);
6555 child_scroll->SetDrawsContent(false);
6557 scroll_layer->AddChild(child_scroll.Pass());
6559 DrawFrame();
6561 // We should not have scrolled |child_scroll| even though we technically "hit"
6562 // it. The reason for this is that if the scrolling the scroll would not move
6563 // any layer that is a drawn RSLL member, then we can ignore the hit.
6565 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6566 // started scrolling the inner viewport.
6567 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6568 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6570 EXPECT_EQ(2, host_impl_->CurrentlyScrollingLayer()->id());
6573 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleDescendent) {
6574 gfx::Size content_size(100, 100);
6575 SetupScrollAndContentsLayers(content_size);
6577 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6578 LayerImpl* root_scroll_layer = host_impl_->active_tree()->LayerById(2);
6580 scoped_ptr<LayerImpl> invisible_scroll_layer =
6581 CreateScrollableLayer(7, content_size, root);
6582 invisible_scroll_layer->SetDrawsContent(false);
6584 scoped_ptr<LayerImpl> child_layer =
6585 LayerImpl::Create(host_impl_->active_tree(), 8);
6586 child_layer->SetDrawsContent(false);
6588 scoped_ptr<LayerImpl> grand_child_layer =
6589 LayerImpl::Create(host_impl_->active_tree(), 9);
6590 grand_child_layer->SetDrawsContent(true);
6591 grand_child_layer->SetBounds(content_size);
6592 // Move the grand child so it's not hit by our test point.
6593 grand_child_layer->SetPosition(gfx::PointF(10.f, 10.f));
6595 child_layer->AddChild(grand_child_layer.Pass());
6596 invisible_scroll_layer->AddChild(child_layer.Pass());
6597 root_scroll_layer->AddChild(invisible_scroll_layer.Pass());
6599 DrawFrame();
6601 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6602 // a descendant which is a drawn RSLL member.
6603 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6604 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6606 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6609 TEST_F(LayerTreeHostImplTest, ScrollInvisibleScrollerWithVisibleScrollChild) {
6610 // This test case is very similar to the one above with one key difference:
6611 // the invisible scroller has a scroll child that is indeed draw contents.
6612 // If we attempt to initiate a gesture scroll off of the visible scroll child
6613 // we should still start the scroll child.
6614 gfx::Size content_size(100, 100);
6615 SetupScrollAndContentsLayers(content_size);
6617 LayerImpl* root = host_impl_->active_tree()->LayerById(1);
6619 int scroll_layer_id = 2;
6620 LayerImpl* scroll_layer =
6621 host_impl_->active_tree()->LayerById(scroll_layer_id);
6623 int scroll_child_id = 6;
6624 scoped_ptr<LayerImpl> scroll_child =
6625 LayerImpl::Create(host_impl_->active_tree(), scroll_child_id);
6626 scroll_child->SetDrawsContent(true);
6627 scroll_child->SetBounds(content_size);
6628 // Move the scroll child so it's not hit by our test point.
6629 scroll_child->SetPosition(gfx::PointF(10.f, 10.f));
6631 int invisible_scroll_layer_id = 7;
6632 scoped_ptr<LayerImpl> invisible_scroll =
6633 CreateScrollableLayer(invisible_scroll_layer_id, content_size, root);
6634 invisible_scroll->SetDrawsContent(false);
6636 int container_id = 8;
6637 scoped_ptr<LayerImpl> container =
6638 LayerImpl::Create(host_impl_->active_tree(), container_id);
6640 scoped_ptr<std::set<LayerImpl*>> scroll_children(new std::set<LayerImpl*>);
6641 scroll_children->insert(scroll_child.get());
6642 invisible_scroll->SetScrollChildren(scroll_children.release());
6644 scroll_child->SetScrollParent(invisible_scroll.get());
6646 container->AddChild(invisible_scroll.Pass());
6647 container->AddChild(scroll_child.Pass());
6649 scroll_layer->AddChild(container.Pass());
6651 DrawFrame();
6653 // We should have scrolled |child_scroll| even though it is invisible.
6654 // The reason for this is that if the scrolling the scroll would move a layer
6655 // that is a drawn RSLL member, then we should accept this hit.
6656 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6657 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
6659 EXPECT_EQ(7, host_impl_->CurrentlyScrollingLayer()->id());
6662 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6663 // to CompositorFrameMetadata after SwapBuffers();
6664 TEST_F(LayerTreeHostImplTest, LatencyInfoPassedToCompositorFrameMetadata) {
6665 scoped_ptr<SolidColorLayerImpl> root =
6666 SolidColorLayerImpl::Create(host_impl_->active_tree(), 1);
6667 root->SetPosition(gfx::PointF());
6668 root->SetBounds(gfx::Size(10, 10));
6669 root->SetDrawsContent(true);
6670 root->SetHasRenderSurface(true);
6672 host_impl_->active_tree()->SetRootLayer(root.Pass());
6674 FakeOutputSurface* fake_output_surface =
6675 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6677 const std::vector<ui::LatencyInfo>& metadata_latency_before =
6678 fake_output_surface->last_sent_frame().metadata.latency_info;
6679 EXPECT_TRUE(metadata_latency_before.empty());
6681 ui::LatencyInfo latency_info;
6682 latency_info.AddLatencyNumber(
6683 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, 0);
6684 scoped_ptr<SwapPromise> swap_promise(
6685 new LatencyInfoSwapPromise(latency_info));
6686 host_impl_->active_tree()->QueueSwapPromise(swap_promise.Pass());
6687 host_impl_->SetNeedsRedraw();
6689 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6690 LayerTreeHostImpl::FrameData frame;
6691 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6692 host_impl_->DrawLayers(&frame);
6693 host_impl_->DidDrawAllLayers(frame);
6694 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6696 const std::vector<ui::LatencyInfo>& metadata_latency_after =
6697 fake_output_surface->last_sent_frame().metadata.latency_info;
6698 EXPECT_EQ(1u, metadata_latency_after.size());
6699 EXPECT_TRUE(metadata_latency_after[0].FindLatency(
6700 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, NULL));
6703 TEST_F(LayerTreeHostImplTest, SelectionBoundsPassedToCompositorFrameMetadata) {
6704 int root_layer_id = 1;
6705 scoped_ptr<SolidColorLayerImpl> root =
6706 SolidColorLayerImpl::Create(host_impl_->active_tree(), root_layer_id);
6707 root->SetPosition(gfx::PointF());
6708 root->SetBounds(gfx::Size(10, 10));
6709 root->SetDrawsContent(true);
6710 root->SetHasRenderSurface(true);
6712 host_impl_->active_tree()->SetRootLayer(root.Pass());
6714 // Ensure the default frame selection bounds are empty.
6715 FakeOutputSurface* fake_output_surface =
6716 static_cast<FakeOutputSurface*>(host_impl_->output_surface());
6717 const ViewportSelection& selection_before =
6718 fake_output_surface->last_sent_frame().metadata.selection;
6719 EXPECT_EQ(ViewportSelectionBound(), selection_before.start);
6720 EXPECT_EQ(ViewportSelectionBound(), selection_before.end);
6722 // Plumb the layer-local selection bounds.
6723 gfx::PointF selection_top(5, 0);
6724 gfx::PointF selection_bottom(5, 5);
6725 LayerSelection selection;
6726 selection.start.type = SELECTION_BOUND_CENTER;
6727 selection.start.layer_id = root_layer_id;
6728 selection.start.edge_bottom = selection_bottom;
6729 selection.start.edge_top = selection_top;
6730 selection.end = selection.start;
6731 host_impl_->active_tree()->RegisterSelection(selection);
6733 // Trigger a draw-swap sequence.
6734 host_impl_->SetNeedsRedraw();
6736 gfx::Rect full_frame_damage(host_impl_->DrawViewportSize());
6737 LayerTreeHostImpl::FrameData frame;
6738 EXPECT_EQ(DRAW_SUCCESS, host_impl_->PrepareToDraw(&frame));
6739 host_impl_->DrawLayers(&frame);
6740 host_impl_->DidDrawAllLayers(frame);
6741 EXPECT_TRUE(host_impl_->SwapBuffers(frame));
6743 // Ensure the selection bounds have propagated to the frame metadata.
6744 const ViewportSelection& selection_after =
6745 fake_output_surface->last_sent_frame().metadata.selection;
6746 EXPECT_EQ(selection.start.type, selection_after.start.type);
6747 EXPECT_EQ(selection.end.type, selection_after.end.type);
6748 EXPECT_EQ(selection_bottom, selection_after.start.edge_bottom);
6749 EXPECT_EQ(selection_top, selection_after.start.edge_top);
6750 EXPECT_TRUE(selection_after.start.visible);
6751 EXPECT_TRUE(selection_after.start.visible);
6754 class SimpleSwapPromiseMonitor : public SwapPromiseMonitor {
6755 public:
6756 SimpleSwapPromiseMonitor(LayerTreeHost* layer_tree_host,
6757 LayerTreeHostImpl* layer_tree_host_impl,
6758 int* set_needs_commit_count,
6759 int* set_needs_redraw_count,
6760 int* forward_to_main_count)
6761 : SwapPromiseMonitor(layer_tree_host, layer_tree_host_impl),
6762 set_needs_commit_count_(set_needs_commit_count),
6763 set_needs_redraw_count_(set_needs_redraw_count),
6764 forward_to_main_count_(forward_to_main_count) {}
6766 ~SimpleSwapPromiseMonitor() override {}
6768 void OnSetNeedsCommitOnMain() override { (*set_needs_commit_count_)++; }
6770 void OnSetNeedsRedrawOnImpl() override { (*set_needs_redraw_count_)++; }
6772 void OnForwardScrollUpdateToMainThreadOnImpl() override {
6773 (*forward_to_main_count_)++;
6776 private:
6777 int* set_needs_commit_count_;
6778 int* set_needs_redraw_count_;
6779 int* forward_to_main_count_;
6782 TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) {
6783 int set_needs_commit_count = 0;
6784 int set_needs_redraw_count = 0;
6785 int forward_to_main_count = 0;
6788 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6789 new SimpleSwapPromiseMonitor(NULL,
6790 host_impl_.get(),
6791 &set_needs_commit_count,
6792 &set_needs_redraw_count,
6793 &forward_to_main_count));
6794 host_impl_->SetNeedsRedraw();
6795 EXPECT_EQ(0, set_needs_commit_count);
6796 EXPECT_EQ(1, set_needs_redraw_count);
6797 EXPECT_EQ(0, forward_to_main_count);
6800 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6801 // monitored.
6802 host_impl_->SetNeedsRedraw();
6803 EXPECT_EQ(0, set_needs_commit_count);
6804 EXPECT_EQ(1, set_needs_redraw_count);
6805 EXPECT_EQ(0, forward_to_main_count);
6808 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6809 new SimpleSwapPromiseMonitor(NULL,
6810 host_impl_.get(),
6811 &set_needs_commit_count,
6812 &set_needs_redraw_count,
6813 &forward_to_main_count));
6814 host_impl_->SetNeedsRedrawRect(gfx::Rect(10, 10));
6815 EXPECT_EQ(0, set_needs_commit_count);
6816 EXPECT_EQ(2, set_needs_redraw_count);
6817 EXPECT_EQ(0, forward_to_main_count);
6821 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6822 new SimpleSwapPromiseMonitor(NULL,
6823 host_impl_.get(),
6824 &set_needs_commit_count,
6825 &set_needs_redraw_count,
6826 &forward_to_main_count));
6827 // Empty damage rect won't signal the monitor.
6828 host_impl_->SetNeedsRedrawRect(gfx::Rect());
6829 EXPECT_EQ(0, set_needs_commit_count);
6830 EXPECT_EQ(2, set_needs_redraw_count);
6831 EXPECT_EQ(0, forward_to_main_count);
6835 set_needs_commit_count = 0;
6836 set_needs_redraw_count = 0;
6837 forward_to_main_count = 0;
6838 scoped_ptr<SimpleSwapPromiseMonitor> swap_promise_monitor(
6839 new SimpleSwapPromiseMonitor(NULL,
6840 host_impl_.get(),
6841 &set_needs_commit_count,
6842 &set_needs_redraw_count,
6843 &forward_to_main_count));
6844 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
6846 // Scrolling normally should not trigger any forwarding.
6847 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6848 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6849 EXPECT_TRUE(
6850 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6851 host_impl_->ScrollEnd();
6853 EXPECT_EQ(0, set_needs_commit_count);
6854 EXPECT_EQ(1, set_needs_redraw_count);
6855 EXPECT_EQ(0, forward_to_main_count);
6857 // Scrolling with a scroll handler should defer the swap to the main
6858 // thread.
6859 scroll_layer->SetHaveScrollEventHandlers(true);
6860 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6861 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6862 EXPECT_TRUE(
6863 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll);
6864 host_impl_->ScrollEnd();
6866 EXPECT_EQ(0, set_needs_commit_count);
6867 EXPECT_EQ(2, set_needs_redraw_count);
6868 EXPECT_EQ(1, forward_to_main_count);
6872 class LayerTreeHostImplWithTopControlsTest : public LayerTreeHostImplTest {
6873 public:
6874 void SetUp() override {
6875 LayerTreeSettings settings = DefaultSettings();
6876 CreateHostImpl(settings, CreateOutputSurface());
6877 host_impl_->active_tree()->set_top_controls_height(top_controls_height_);
6878 host_impl_->sync_tree()->set_top_controls_height(top_controls_height_);
6879 host_impl_->active_tree()->SetCurrentTopControlsShownRatio(1.f);
6882 protected:
6883 static const int top_controls_height_;
6886 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_ = 50;
6888 TEST_F(LayerTreeHostImplWithTopControlsTest, NoIdleAnimations) {
6889 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6890 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6891 host_impl_->Animate(base::TimeTicks());
6892 EXPECT_FALSE(did_request_redraw_);
6895 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsHeightIsCommitted) {
6896 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6897 EXPECT_FALSE(did_request_redraw_);
6898 host_impl_->CreatePendingTree();
6899 host_impl_->sync_tree()->set_top_controls_height(100);
6900 host_impl_->ActivateSyncTree();
6901 EXPECT_EQ(100, host_impl_->top_controls_manager()->TopControlsHeight());
6904 TEST_F(LayerTreeHostImplWithTopControlsTest,
6905 TopControlsStayFullyVisibleOnHeightChange) {
6906 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6907 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6909 host_impl_->CreatePendingTree();
6910 host_impl_->sync_tree()->set_top_controls_height(0);
6911 host_impl_->ActivateSyncTree();
6912 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6914 host_impl_->CreatePendingTree();
6915 host_impl_->sync_tree()->set_top_controls_height(50);
6916 host_impl_->ActivateSyncTree();
6917 EXPECT_EQ(0.f, host_impl_->top_controls_manager()->ControlsTopOffset());
6920 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationScheduling) {
6921 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6922 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6923 host_impl_->DidChangeTopControlsPosition();
6924 EXPECT_TRUE(did_request_animate_);
6925 EXPECT_TRUE(did_request_redraw_);
6928 TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) {
6929 InputHandlerScrollResult result;
6930 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
6931 host_impl_->SetViewportSize(gfx::Size(100, 100));
6932 host_impl_->top_controls_manager()->UpdateTopControlsState(
6933 BOTH, SHOWN, false);
6934 DrawFrame();
6936 EXPECT_EQ(InputHandler::SCROLL_STARTED,
6937 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
6938 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6939 EXPECT_EQ(gfx::Vector2dF().ToString(),
6940 scroll_layer->CurrentScrollOffset().ToString());
6942 // Scroll just the top controls and verify that the scroll succeeds.
6943 const float residue = 10;
6944 float offset = top_controls_height_ - residue;
6945 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
6946 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
6947 EXPECT_TRUE(result.did_scroll);
6948 EXPECT_FLOAT_EQ(-offset,
6949 host_impl_->top_controls_manager()->ControlsTopOffset());
6950 EXPECT_EQ(gfx::Vector2dF().ToString(),
6951 scroll_layer->CurrentScrollOffset().ToString());
6953 // Scroll across the boundary
6954 const float content_scroll = 20;
6955 offset = residue + content_scroll;
6956 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
6957 EXPECT_TRUE(result.did_scroll);
6958 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
6959 EXPECT_EQ(-top_controls_height_,
6960 host_impl_->top_controls_manager()->ControlsTopOffset());
6961 EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(),
6962 scroll_layer->CurrentScrollOffset().ToString());
6964 // Now scroll back to the top of the content
6965 offset = -content_scroll;
6966 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
6967 EXPECT_TRUE(result.did_scroll);
6968 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
6969 EXPECT_EQ(-top_controls_height_,
6970 host_impl_->top_controls_manager()->ControlsTopOffset());
6971 EXPECT_EQ(gfx::Vector2dF().ToString(),
6972 scroll_layer->CurrentScrollOffset().ToString());
6974 // And scroll the top controls completely into view
6975 offset = -top_controls_height_;
6976 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
6977 EXPECT_TRUE(result.did_scroll);
6978 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, 0));
6979 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6980 EXPECT_EQ(gfx::Vector2dF().ToString(),
6981 scroll_layer->CurrentScrollOffset().ToString());
6983 // And attempt to scroll past the end
6984 result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset));
6985 EXPECT_FALSE(result.did_scroll);
6986 EXPECT_EQ(result.unused_scroll_delta, gfx::Vector2d(0, -50));
6987 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
6988 EXPECT_EQ(gfx::Vector2dF().ToString(),
6989 scroll_layer->CurrentScrollOffset().ToString());
6991 host_impl_->ScrollEnd();
6994 TEST_F(LayerTreeHostImplWithTopControlsTest, WheelUnhandledByTopControls) {
6995 SetupScrollAndContentsLayers(gfx::Size(100, 200));
6996 host_impl_->SetViewportSize(gfx::Size(50, 100));
6997 host_impl_->active_tree()->set_top_controls_shrink_blink_size(true);
6998 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
6999 false);
7000 DrawFrame();
7002 LayerImpl* viewport_layer = host_impl_->InnerViewportScrollLayer();
7004 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7005 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7006 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7007 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer->CurrentScrollOffset());
7009 // Wheel scrolls should not affect the top controls, and should pass
7010 // directly through to the viewport.
7011 const float delta = top_controls_height_;
7012 EXPECT_TRUE(
7013 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
7014 EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7015 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta),
7016 viewport_layer->CurrentScrollOffset());
7018 EXPECT_TRUE(
7019 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta)).did_scroll);
7020 EXPECT_FLOAT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7021 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta * 2),
7022 viewport_layer->CurrentScrollOffset());
7025 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) {
7026 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7027 host_impl_->SetViewportSize(gfx::Size(100, 200));
7028 host_impl_->top_controls_manager()->UpdateTopControlsState(
7029 BOTH, SHOWN, false);
7030 DrawFrame();
7032 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7033 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7034 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7035 EXPECT_EQ(gfx::Vector2dF().ToString(),
7036 scroll_layer->CurrentScrollOffset().ToString());
7038 // Scroll the top controls partially.
7039 const float residue = 35;
7040 float offset = top_controls_height_ - residue;
7041 EXPECT_TRUE(
7042 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7043 EXPECT_FLOAT_EQ(-offset,
7044 host_impl_->top_controls_manager()->ControlsTopOffset());
7045 EXPECT_EQ(gfx::Vector2dF().ToString(),
7046 scroll_layer->CurrentScrollOffset().ToString());
7048 did_request_redraw_ = false;
7049 did_request_animate_ = false;
7050 did_request_commit_ = false;
7052 // End the scroll while the controls are still offset from their limit.
7053 host_impl_->ScrollEnd();
7054 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7055 EXPECT_TRUE(did_request_animate_);
7056 EXPECT_TRUE(did_request_redraw_);
7057 EXPECT_FALSE(did_request_commit_);
7059 // The top controls should properly animate until finished, despite the scroll
7060 // offset being at the origin.
7061 base::TimeTicks animation_time = base::TimeTicks::Now();
7062 while (did_request_animate_) {
7063 did_request_redraw_ = false;
7064 did_request_animate_ = false;
7065 did_request_commit_ = false;
7067 float old_offset =
7068 host_impl_->top_controls_manager()->ControlsTopOffset();
7070 animation_time += base::TimeDelta::FromMilliseconds(5);
7071 host_impl_->Animate(animation_time);
7072 EXPECT_EQ(gfx::Vector2dF().ToString(),
7073 scroll_layer->CurrentScrollOffset().ToString());
7075 float new_offset =
7076 host_impl_->top_controls_manager()->ControlsTopOffset();
7078 // No commit is needed as the controls are animating the content offset,
7079 // not the scroll offset.
7080 EXPECT_FALSE(did_request_commit_);
7082 if (new_offset != old_offset)
7083 EXPECT_TRUE(did_request_redraw_);
7085 if (new_offset != 0) {
7086 EXPECT_TRUE(host_impl_->top_controls_manager()->animation());
7087 EXPECT_TRUE(did_request_animate_);
7090 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7093 TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) {
7094 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7095 host_impl_->SetViewportSize(gfx::Size(100, 100));
7096 host_impl_->top_controls_manager()->UpdateTopControlsState(
7097 BOTH, SHOWN, false);
7098 float initial_scroll_offset = 50;
7099 scroll_layer->PushScrollOffsetFromMainThread(
7100 gfx::ScrollOffset(0, initial_scroll_offset));
7101 DrawFrame();
7103 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7104 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7105 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7106 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7107 scroll_layer->CurrentScrollOffset().ToString());
7109 // Scroll the top controls partially.
7110 const float residue = 15;
7111 float offset = top_controls_height_ - residue;
7112 EXPECT_TRUE(
7113 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7114 EXPECT_FLOAT_EQ(-offset,
7115 host_impl_->top_controls_manager()->ControlsTopOffset());
7116 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7117 scroll_layer->CurrentScrollOffset().ToString());
7119 did_request_redraw_ = false;
7120 did_request_animate_ = false;
7121 did_request_commit_ = false;
7123 // End the scroll while the controls are still offset from the limit.
7124 host_impl_->ScrollEnd();
7125 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7126 EXPECT_TRUE(did_request_animate_);
7127 EXPECT_TRUE(did_request_redraw_);
7128 EXPECT_FALSE(did_request_commit_);
7130 // Animate the top controls to the limit.
7131 base::TimeTicks animation_time = base::TimeTicks::Now();
7132 while (did_request_animate_) {
7133 did_request_redraw_ = false;
7134 did_request_animate_ = false;
7135 did_request_commit_ = false;
7137 float old_offset =
7138 host_impl_->top_controls_manager()->ControlsTopOffset();
7140 animation_time += base::TimeDelta::FromMilliseconds(5);
7141 host_impl_->Animate(animation_time);
7143 float new_offset =
7144 host_impl_->top_controls_manager()->ControlsTopOffset();
7146 if (new_offset != old_offset) {
7147 EXPECT_TRUE(did_request_redraw_);
7148 EXPECT_TRUE(did_request_commit_);
7151 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7152 EXPECT_EQ(-top_controls_height_,
7153 host_impl_->top_controls_manager()->ControlsTopOffset());
7156 TEST_F(LayerTreeHostImplWithTopControlsTest,
7157 TopControlsAnimationAfterMainThreadFlingStopped) {
7158 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7159 host_impl_->SetViewportSize(gfx::Size(100, 100));
7160 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7161 false);
7162 float initial_scroll_offset = 50;
7163 scroll_layer->PushScrollOffsetFromMainThread(
7164 gfx::ScrollOffset(0, initial_scroll_offset));
7165 DrawFrame();
7167 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7168 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7169 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7170 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7171 scroll_layer->CurrentScrollOffset().ToString());
7173 // Scroll the top controls partially.
7174 const float residue = 15;
7175 float offset = top_controls_height_ - residue;
7176 EXPECT_TRUE(
7177 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7178 EXPECT_FLOAT_EQ(-offset,
7179 host_impl_->top_controls_manager()->ControlsTopOffset());
7180 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(),
7181 scroll_layer->CurrentScrollOffset().ToString());
7183 did_request_redraw_ = false;
7184 did_request_animate_ = false;
7185 did_request_commit_ = false;
7187 // End the fling while the controls are still offset from the limit.
7188 host_impl_->MainThreadHasStoppedFlinging();
7189 ASSERT_TRUE(host_impl_->top_controls_manager()->animation());
7190 EXPECT_TRUE(did_request_animate_);
7191 EXPECT_TRUE(did_request_redraw_);
7192 EXPECT_FALSE(did_request_commit_);
7194 // Animate the top controls to the limit.
7195 base::TimeTicks animation_time = base::TimeTicks::Now();
7196 while (did_request_animate_) {
7197 did_request_redraw_ = false;
7198 did_request_animate_ = false;
7199 did_request_commit_ = false;
7201 float old_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7203 animation_time += base::TimeDelta::FromMilliseconds(5);
7204 host_impl_->Animate(animation_time);
7206 float new_offset = host_impl_->top_controls_manager()->ControlsTopOffset();
7208 if (new_offset != old_offset) {
7209 EXPECT_TRUE(did_request_redraw_);
7210 EXPECT_TRUE(did_request_commit_);
7213 EXPECT_FALSE(host_impl_->top_controls_manager()->animation());
7214 EXPECT_EQ(-top_controls_height_,
7215 host_impl_->top_controls_manager()->ControlsTopOffset());
7218 TEST_F(LayerTreeHostImplWithTopControlsTest,
7219 TopControlsScrollDeltaInOverScroll) {
7220 // Verifies that the overscroll delta should not have accumulated in
7221 // the top controls if we do a hide and show without releasing finger.
7223 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 200));
7224 host_impl_->SetViewportSize(gfx::Size(100, 100));
7225 host_impl_->top_controls_manager()->UpdateTopControlsState(BOTH, SHOWN,
7226 false);
7227 DrawFrame();
7229 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7230 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7231 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7233 float offset = 50;
7234 EXPECT_TRUE(
7235 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7236 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7237 EXPECT_EQ(gfx::Vector2dF().ToString(),
7238 scroll_layer->CurrentScrollOffset().ToString());
7240 EXPECT_TRUE(
7241 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7242 EXPECT_EQ(gfx::Vector2dF(0, offset).ToString(),
7243 scroll_layer->CurrentScrollOffset().ToString());
7245 EXPECT_TRUE(
7246 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll);
7248 // Should have fully scrolled
7249 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer->MaxScrollOffset().y()).ToString(),
7250 scroll_layer->CurrentScrollOffset().ToString());
7252 float overscrollamount = 10;
7254 // Overscroll the content
7255 EXPECT_FALSE(
7256 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount))
7257 .did_scroll);
7258 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset).ToString(),
7259 scroll_layer->CurrentScrollOffset().ToString());
7260 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount).ToString(),
7261 host_impl_->accumulated_root_overscroll().ToString());
7263 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset))
7264 .did_scroll);
7265 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7266 scroll_layer->CurrentScrollOffset().ToString());
7267 EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset());
7269 EXPECT_TRUE(
7270 host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset)).did_scroll);
7271 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7272 scroll_layer->CurrentScrollOffset().ToString());
7274 // Top controls should be fully visible
7275 EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset());
7277 host_impl_->ScrollEnd();
7280 class LayerTreeHostImplVirtualViewportTest : public LayerTreeHostImplTest {
7281 public:
7282 void SetupVirtualViewportLayers(const gfx::Size& content_size,
7283 const gfx::Size& outer_viewport,
7284 const gfx::Size& inner_viewport) {
7285 LayerTreeImpl* layer_tree_impl = host_impl_->active_tree();
7286 const int kOuterViewportClipLayerId = 6;
7287 const int kOuterViewportScrollLayerId = 7;
7288 const int kInnerViewportScrollLayerId = 2;
7289 const int kInnerViewportClipLayerId = 4;
7290 const int kPageScaleLayerId = 5;
7292 scoped_ptr<LayerImpl> inner_scroll =
7293 LayerImpl::Create(layer_tree_impl, kInnerViewportScrollLayerId);
7294 inner_scroll->SetIsContainerForFixedPositionLayers(true);
7295 inner_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7297 scoped_ptr<LayerImpl> inner_clip =
7298 LayerImpl::Create(layer_tree_impl, kInnerViewportClipLayerId);
7299 inner_clip->SetBounds(inner_viewport);
7301 scoped_ptr<LayerImpl> page_scale =
7302 LayerImpl::Create(layer_tree_impl, kPageScaleLayerId);
7304 inner_scroll->SetScrollClipLayer(inner_clip->id());
7305 inner_scroll->SetBounds(outer_viewport);
7306 inner_scroll->SetPosition(gfx::PointF());
7308 scoped_ptr<LayerImpl> outer_clip =
7309 LayerImpl::Create(layer_tree_impl, kOuterViewportClipLayerId);
7310 outer_clip->SetBounds(outer_viewport);
7311 outer_clip->SetIsContainerForFixedPositionLayers(true);
7313 scoped_ptr<LayerImpl> outer_scroll =
7314 LayerImpl::Create(layer_tree_impl, kOuterViewportScrollLayerId);
7315 outer_scroll->SetScrollClipLayer(outer_clip->id());
7316 outer_scroll->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7317 outer_scroll->SetBounds(content_size);
7318 outer_scroll->SetPosition(gfx::PointF());
7320 scoped_ptr<LayerImpl> contents =
7321 LayerImpl::Create(layer_tree_impl, 8);
7322 contents->SetDrawsContent(true);
7323 contents->SetBounds(content_size);
7324 contents->SetPosition(gfx::PointF());
7326 outer_scroll->AddChild(contents.Pass());
7327 outer_clip->AddChild(outer_scroll.Pass());
7328 inner_scroll->AddChild(outer_clip.Pass());
7329 page_scale->AddChild(inner_scroll.Pass());
7330 inner_clip->AddChild(page_scale.Pass());
7332 inner_clip->SetHasRenderSurface(true);
7333 layer_tree_impl->SetRootLayer(inner_clip.Pass());
7334 layer_tree_impl->SetViewportLayersFromIds(
7335 Layer::INVALID_ID, kPageScaleLayerId, kInnerViewportScrollLayerId,
7336 kOuterViewportScrollLayerId);
7338 host_impl_->active_tree()->DidBecomeActive();
7342 TEST_F(LayerTreeHostImplVirtualViewportTest, ScrollBothInnerAndOuterLayer) {
7343 gfx::Size content_size = gfx::Size(100, 160);
7344 gfx::Size outer_viewport = gfx::Size(50, 80);
7345 gfx::Size inner_viewport = gfx::Size(25, 40);
7347 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7349 TestScrollOffsetDelegate scroll_delegate;
7350 host_impl_->SetRootLayerScrollOffsetDelegate(&scroll_delegate);
7352 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7353 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7354 DrawFrame();
7356 gfx::ScrollOffset inner_expected;
7357 gfx::ScrollOffset outer_expected;
7358 EXPECT_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7359 EXPECT_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7361 gfx::ScrollOffset current_offset(70.f, 100.f);
7363 scroll_delegate.set_getter_return_value(current_offset);
7364 host_impl_->OnRootLayerDelegatedScrollOffsetChanged();
7365 EXPECT_EQ(gfx::ScrollOffset(25.f, 40.f), inner_scroll->MaxScrollOffset());
7366 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f), outer_scroll->MaxScrollOffset());
7368 // Outer viewport scrolls first. Then the rest is applied to the inner
7369 // viewport.
7370 EXPECT_EQ(gfx::ScrollOffset(20.f, 20.f),
7371 inner_scroll->CurrentScrollOffset());
7372 EXPECT_EQ(gfx::ScrollOffset(50.f, 80.f),
7373 outer_scroll->CurrentScrollOffset());
7377 TEST_F(LayerTreeHostImplVirtualViewportTest, FlingScrollBubblesToInner) {
7378 gfx::Size content_size = gfx::Size(100, 160);
7379 gfx::Size outer_viewport = gfx::Size(50, 80);
7380 gfx::Size inner_viewport = gfx::Size(25, 40);
7382 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7384 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7385 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7386 DrawFrame();
7388 gfx::Vector2dF inner_expected;
7389 gfx::Vector2dF outer_expected;
7390 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7391 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7393 // Make sure the fling goes to the outer viewport first
7394 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7395 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7396 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7397 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7398 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7400 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7401 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7402 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7403 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), outer_scroll);
7405 host_impl_->ScrollEnd();
7406 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7408 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7409 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7411 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7412 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7413 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7414 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7415 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7416 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7418 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7419 outer_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7420 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7422 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7423 inner_expected += gfx::Vector2dF(scroll_delta.x(), scroll_delta.y());
7424 EXPECT_EQ(outer_scroll, host_impl_->CurrentlyScrollingLayer());
7426 host_impl_->ScrollEnd();
7427 EXPECT_EQ(nullptr, host_impl_->CurrentlyScrollingLayer());
7429 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7430 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7434 TEST_F(LayerTreeHostImplVirtualViewportTest,
7435 DiagonalScrollBubblesPerfectlyToInner) {
7436 gfx::Size content_size = gfx::Size(100, 160);
7437 gfx::Size outer_viewport = gfx::Size(50, 80);
7438 gfx::Size inner_viewport = gfx::Size(25, 40);
7440 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7442 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7443 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7444 DrawFrame();
7446 gfx::Vector2dF inner_expected;
7447 gfx::Vector2dF outer_expected;
7448 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7449 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7451 // Make sure the scroll goes to the outer viewport first.
7452 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7453 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7454 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7455 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7456 InputHandler::GESTURE));
7458 // Scroll near the edge of the outer viewport.
7459 gfx::Vector2d scroll_delta(inner_viewport.width(), inner_viewport.height());
7460 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7461 outer_expected += scroll_delta;
7462 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7463 InputHandler::GESTURE));
7465 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7466 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7468 // Now diagonal scroll across the outer viewport boundary in a single event.
7469 // The entirety of the scroll should be consumed, as bubbling between inner
7470 // and outer viewport layers is perfect.
7471 host_impl_->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta, 2));
7472 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7473 InputHandler::GESTURE));
7474 outer_expected += scroll_delta;
7475 inner_expected += scroll_delta;
7476 host_impl_->ScrollEnd();
7477 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7478 gfx::Point(), InputHandler::GESTURE));
7480 EXPECT_VECTOR_EQ(inner_expected, inner_scroll->CurrentScrollOffset());
7481 EXPECT_VECTOR_EQ(outer_expected, outer_scroll->CurrentScrollOffset());
7485 TEST_F(LayerTreeHostImplVirtualViewportTest,
7486 TouchFlingCanLockToViewportLayerAfterBubbling) {
7487 gfx::Size content_size = gfx::Size(100, 160);
7488 gfx::Size outer_viewport = gfx::Size(50, 80);
7489 gfx::Size inner_viewport = gfx::Size(25, 40);
7491 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7493 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7494 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7496 scoped_ptr<LayerImpl> child =
7497 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7498 LayerImpl* child_scroll = child.get();
7499 outer_scroll->children()[0]->AddChild(child.Pass());
7501 DrawFrame();
7503 scoped_ptr<ScrollAndScaleSet> scroll_info;
7505 gfx::Vector2d scroll_delta(0, inner_viewport.height());
7506 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7507 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7508 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7509 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7510 InputHandler::GESTURE));
7512 // The child should have scrolled up to its limit.
7513 scroll_info = host_impl_->ProcessScrollDeltas();
7514 ASSERT_EQ(1u, scroll_info->scrolls.size());
7515 EXPECT_TRUE(
7516 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7517 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7519 // The first |ScrollBy| after the fling should re-lock the scrolling
7520 // layer to the first layer that scrolled, the inner viewport scroll layer.
7521 EXPECT_EQ(InputHandler::SCROLL_STARTED, host_impl_->FlingScrollBegin());
7522 EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7523 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7524 EXPECT_TRUE(host_impl_->IsCurrentlyScrollingLayerAt(gfx::Point(),
7525 InputHandler::GESTURE));
7527 // The inner viewport should have scrolled up to its limit.
7528 scroll_info = host_impl_->ProcessScrollDeltas();
7529 ASSERT_EQ(2u, scroll_info->scrolls.size());
7530 EXPECT_TRUE(
7531 ScrollInfoContains(*scroll_info, child_scroll->id(), scroll_delta));
7532 EXPECT_TRUE(
7533 ScrollInfoContains(*scroll_info, inner_scroll->id(), scroll_delta));
7535 // As the locked layer is at its limit, no further scrolling can occur.
7536 EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll);
7537 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7538 host_impl_->ScrollEnd();
7539 EXPECT_FALSE(host_impl_->IsCurrentlyScrollingLayerAt(
7540 gfx::Point(), InputHandler::GESTURE));
7544 TEST_F(LayerTreeHostImplVirtualViewportTest,
7545 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest) {
7546 gfx::Size content_size = gfx::Size(100, 160);
7547 gfx::Size outer_viewport = gfx::Size(50, 80);
7548 gfx::Size inner_viewport = gfx::Size(25, 40);
7550 SetupVirtualViewportLayers(content_size, outer_viewport, inner_viewport);
7552 LayerImpl* outer_scroll = host_impl_->OuterViewportScrollLayer();
7553 LayerImpl* inner_scroll = host_impl_->InnerViewportScrollLayer();
7555 scoped_ptr<LayerImpl> child =
7556 CreateScrollableLayer(10, outer_viewport, outer_scroll);
7557 LayerImpl* child_scroll = child.get();
7558 outer_scroll->children()[0]->AddChild(child.Pass());
7560 DrawFrame();
7562 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7563 host_impl_->RootScrollBegin(InputHandler::GESTURE));
7564 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), inner_scroll);
7565 host_impl_->ScrollEnd();
7566 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7567 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE));
7568 EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child_scroll);
7569 host_impl_->ScrollEnd();
7572 class LayerTreeHostImplWithImplicitLimitsTest : public LayerTreeHostImplTest {
7573 public:
7574 void SetUp() override {
7575 LayerTreeSettings settings = DefaultSettings();
7576 settings.max_memory_for_prepaint_percentage = 50;
7577 CreateHostImpl(settings, CreateOutputSurface());
7581 TEST_F(LayerTreeHostImplWithImplicitLimitsTest, ImplicitMemoryLimits) {
7582 // Set up a memory policy and percentages which could cause
7583 // 32-bit integer overflows.
7584 ManagedMemoryPolicy mem_policy(300 * 1024 * 1024); // 300MB
7586 // Verify implicit limits are calculated correctly with no overflows
7587 host_impl_->SetMemoryPolicy(mem_policy);
7588 EXPECT_EQ(host_impl_->global_tile_state().hard_memory_limit_in_bytes,
7589 300u * 1024u * 1024u);
7590 EXPECT_EQ(host_impl_->global_tile_state().soft_memory_limit_in_bytes,
7591 150u * 1024u * 1024u);
7594 TEST_F(LayerTreeHostImplTest, ExternalTransformReflectedInNextDraw) {
7595 const gfx::Size layer_size(100, 100);
7596 gfx::Transform external_transform;
7597 const gfx::Rect external_viewport(layer_size);
7598 const gfx::Rect external_clip(layer_size);
7599 const bool resourceless_software_draw = false;
7600 LayerImpl* layer = SetupScrollAndContentsLayers(layer_size);
7602 host_impl_->SetExternalDrawConstraints(external_transform,
7603 external_viewport,
7604 external_clip,
7605 external_viewport,
7606 external_transform,
7607 resourceless_software_draw);
7608 DrawFrame();
7609 EXPECT_TRANSFORMATION_MATRIX_EQ(
7610 external_transform, layer->draw_properties().target_space_transform);
7612 external_transform.Translate(20, 20);
7613 host_impl_->SetExternalDrawConstraints(external_transform,
7614 external_viewport,
7615 external_clip,
7616 external_viewport,
7617 external_transform,
7618 resourceless_software_draw);
7619 DrawFrame();
7620 EXPECT_TRANSFORMATION_MATRIX_EQ(
7621 external_transform, layer->draw_properties().target_space_transform);
7624 TEST_F(LayerTreeHostImplTest, ScrollAnimated) {
7625 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7626 DrawFrame();
7628 base::TimeTicks start_time =
7629 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7631 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7632 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7634 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7636 host_impl_->Animate(start_time);
7637 host_impl_->UpdateAnimationState(true);
7639 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
7641 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7642 host_impl_->UpdateAnimationState(true);
7644 float y = scrolling_layer->CurrentScrollOffset().y();
7645 EXPECT_TRUE(y > 1 && y < 49);
7647 // Update target.
7648 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7649 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7651 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7652 host_impl_->UpdateAnimationState(true);
7654 y = scrolling_layer->CurrentScrollOffset().y();
7655 EXPECT_TRUE(y > 50 && y < 100);
7656 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7658 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7659 host_impl_->UpdateAnimationState(true);
7661 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7662 scrolling_layer->CurrentScrollOffset());
7663 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7666 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
7667 TEST_F(LayerTreeHostImplTimelinesTest, ScrollAnimated) {
7668 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7669 DrawFrame();
7671 base::TimeTicks start_time =
7672 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7674 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7675 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7677 LayerImpl* scrolling_layer = host_impl_->CurrentlyScrollingLayer();
7679 host_impl_->Animate(start_time);
7680 host_impl_->UpdateAnimationState(true);
7682 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer->CurrentScrollOffset());
7684 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(50));
7685 host_impl_->UpdateAnimationState(true);
7687 float y = scrolling_layer->CurrentScrollOffset().y();
7688 EXPECT_TRUE(y > 1 && y < 49);
7690 // Update target.
7691 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7692 host_impl_->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7694 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(200));
7695 host_impl_->UpdateAnimationState(true);
7697 y = scrolling_layer->CurrentScrollOffset().y();
7698 EXPECT_TRUE(y > 50 && y < 100);
7699 EXPECT_EQ(scrolling_layer, host_impl_->CurrentlyScrollingLayer());
7701 host_impl_->Animate(start_time + base::TimeDelta::FromMilliseconds(250));
7702 host_impl_->UpdateAnimationState(true);
7704 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7705 scrolling_layer->CurrentScrollOffset());
7706 EXPECT_EQ(NULL, host_impl_->CurrentlyScrollingLayer());
7709 TEST_F(LayerTreeHostImplTest, InvalidLayerNotAddedToRasterQueue) {
7710 host_impl_->CreatePendingTree();
7712 Region empty_invalidation;
7713 scoped_refptr<RasterSource> pile_with_tiles(
7714 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7715 gfx::Size(10, 10)));
7717 scoped_ptr<FakePictureLayerImpl> layer =
7718 FakePictureLayerImpl::Create(host_impl_->pending_tree(), 11);
7719 layer->SetBounds(gfx::Size(10, 10));
7720 layer->set_gpu_raster_max_texture_size(host_impl_->device_viewport_size());
7721 layer->SetDrawsContent(true);
7722 layer->tilings()->AddTiling(1.0f, pile_with_tiles);
7723 layer->UpdateRasterSource(pile_with_tiles, &empty_invalidation, nullptr);
7724 layer->tilings()->tiling_at(0)->set_resolution(
7725 TileResolution::HIGH_RESOLUTION);
7726 layer->tilings()->tiling_at(0)->CreateAllTilesForTesting();
7727 layer->tilings()->tiling_at(0)->ComputeTilePriorityRects(
7728 gfx::Rect(gfx::Size(10, 10)), 1.f, 1.0, Occlusion());
7729 host_impl_->pending_tree()->SetRootLayer(layer.Pass());
7731 FakePictureLayerImpl* root_layer = static_cast<FakePictureLayerImpl*>(
7732 host_impl_->pending_tree()->root_layer());
7734 root_layer->set_has_valid_tile_priorities(true);
7735 scoped_ptr<RasterTilePriorityQueue> non_empty_raster_priority_queue_all =
7736 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
7737 RasterTilePriorityQueue::Type::ALL);
7738 EXPECT_FALSE(non_empty_raster_priority_queue_all->IsEmpty());
7740 root_layer->set_has_valid_tile_priorities(false);
7741 scoped_ptr<RasterTilePriorityQueue> empty_raster_priority_queue_all =
7742 host_impl_->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES,
7743 RasterTilePriorityQueue::Type::ALL);
7744 EXPECT_TRUE(empty_raster_priority_queue_all->IsEmpty());
7747 TEST_F(LayerTreeHostImplTest, DidBecomeActive) {
7748 host_impl_->CreatePendingTree();
7749 host_impl_->ActivateSyncTree();
7750 host_impl_->CreatePendingTree();
7752 LayerTreeImpl* pending_tree = host_impl_->pending_tree();
7754 scoped_ptr<FakePictureLayerImpl> pending_layer =
7755 FakePictureLayerImpl::Create(pending_tree, 10);
7756 FakePictureLayerImpl* raw_pending_layer = pending_layer.get();
7757 pending_tree->SetRootLayer(pending_layer.Pass());
7758 ASSERT_EQ(raw_pending_layer, pending_tree->root_layer());
7760 EXPECT_EQ(0u, raw_pending_layer->did_become_active_call_count());
7761 pending_tree->DidBecomeActive();
7762 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7764 scoped_ptr<FakePictureLayerImpl> mask_layer =
7765 FakePictureLayerImpl::Create(pending_tree, 11);
7766 FakePictureLayerImpl* raw_mask_layer = mask_layer.get();
7767 raw_pending_layer->SetMaskLayer(mask_layer.Pass());
7768 ASSERT_EQ(raw_mask_layer, raw_pending_layer->mask_layer());
7770 EXPECT_EQ(1u, raw_pending_layer->did_become_active_call_count());
7771 EXPECT_EQ(0u, raw_mask_layer->did_become_active_call_count());
7772 pending_tree->DidBecomeActive();
7773 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7774 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7776 scoped_ptr<FakePictureLayerImpl> replica_layer =
7777 FakePictureLayerImpl::Create(pending_tree, 12);
7778 scoped_ptr<FakePictureLayerImpl> replica_mask_layer =
7779 FakePictureLayerImpl::Create(pending_tree, 13);
7780 FakePictureLayerImpl* raw_replica_mask_layer = replica_mask_layer.get();
7781 replica_layer->SetMaskLayer(replica_mask_layer.Pass());
7782 raw_pending_layer->SetReplicaLayer(replica_layer.Pass());
7783 ASSERT_EQ(raw_replica_mask_layer,
7784 raw_pending_layer->replica_layer()->mask_layer());
7786 EXPECT_EQ(2u, raw_pending_layer->did_become_active_call_count());
7787 EXPECT_EQ(1u, raw_mask_layer->did_become_active_call_count());
7788 EXPECT_EQ(0u, raw_replica_mask_layer->did_become_active_call_count());
7789 pending_tree->DidBecomeActive();
7790 EXPECT_EQ(3u, raw_pending_layer->did_become_active_call_count());
7791 EXPECT_EQ(2u, raw_mask_layer->did_become_active_call_count());
7792 EXPECT_EQ(1u, raw_replica_mask_layer->did_become_active_call_count());
7795 TEST_F(LayerTreeHostImplTest, WheelScrollWithPageScaleFactorOnInnerLayer) {
7796 LayerImpl* scroll_layer = SetupScrollAndContentsLayers(gfx::Size(100, 100));
7797 host_impl_->SetViewportSize(gfx::Size(50, 50));
7798 DrawFrame();
7800 EXPECT_EQ(scroll_layer, host_impl_->InnerViewportScrollLayer());
7802 float min_page_scale = 1.f, max_page_scale = 4.f;
7803 float page_scale_factor = 1.f;
7805 // The scroll deltas should have the page scale factor applied.
7807 host_impl_->active_tree()->PushPageScaleFromMainThread(
7808 page_scale_factor, min_page_scale, max_page_scale);
7809 host_impl_->SetPageScaleOnActiveTree(page_scale_factor);
7810 scroll_layer->SetScrollDelta(gfx::Vector2d());
7812 float page_scale_delta = 2.f;
7813 host_impl_->ScrollBegin(gfx::Point(), InputHandler::GESTURE);
7814 host_impl_->PinchGestureBegin();
7815 host_impl_->PinchGestureUpdate(page_scale_delta, gfx::Point());
7816 host_impl_->PinchGestureEnd();
7817 host_impl_->ScrollEnd();
7819 gfx::Vector2dF scroll_delta(0, 5);
7820 EXPECT_EQ(InputHandler::SCROLL_STARTED,
7821 host_impl_->ScrollBegin(gfx::Point(), InputHandler::WHEEL));
7822 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer->CurrentScrollOffset());
7824 host_impl_->ScrollBy(gfx::Point(), scroll_delta);
7825 host_impl_->ScrollEnd();
7826 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7827 scroll_layer->CurrentScrollOffset());
7831 class LayerTreeHostImplCountingLostSurfaces : public LayerTreeHostImplTest {
7832 public:
7833 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7834 void DidLoseOutputSurfaceOnImplThread() override { num_lost_surfaces_++; }
7836 protected:
7837 int num_lost_surfaces_;
7840 TEST_F(LayerTreeHostImplCountingLostSurfaces, TwiceLostSurface) {
7841 // Really we just need at least one client notification each time
7842 // we go from having a valid output surface to not having a valid output
7843 // surface.
7844 EXPECT_EQ(0, num_lost_surfaces_);
7845 host_impl_->DidLoseOutputSurface();
7846 EXPECT_EQ(1, num_lost_surfaces_);
7847 host_impl_->DidLoseOutputSurface();
7848 EXPECT_LE(1, num_lost_surfaces_);
7851 TEST_F(LayerTreeHostImplTest, RemoveUnreferencedRenderPass) {
7852 LayerTreeHostImpl::FrameData frame;
7853 frame.render_passes.push_back(RenderPass::Create());
7854 RenderPass* pass3 = frame.render_passes.back();
7855 frame.render_passes.push_back(RenderPass::Create());
7856 RenderPass* pass2 = frame.render_passes.back();
7857 frame.render_passes.push_back(RenderPass::Create());
7858 RenderPass* pass1 = frame.render_passes.back();
7860 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7861 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7862 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7864 frame.render_passes_by_id[pass1->id] = pass1;
7865 frame.render_passes_by_id[pass2->id] = pass2;
7866 frame.render_passes_by_id[pass3->id] = pass3;
7868 // Add a quad to each pass so they aren't empty.
7869 SolidColorDrawQuad* color_quad;
7870 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7871 color_quad->material = DrawQuad::SOLID_COLOR;
7872 color_quad = pass2->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7873 color_quad->material = DrawQuad::SOLID_COLOR;
7874 color_quad = pass3->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7875 color_quad->material = DrawQuad::SOLID_COLOR;
7877 // pass3 is referenced by pass2.
7878 RenderPassDrawQuad* rpdq =
7879 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7880 rpdq->material = DrawQuad::RENDER_PASS;
7881 rpdq->render_pass_id = pass3->id;
7883 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7884 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7885 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7886 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7887 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7888 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7889 EXPECT_EQ(1u, frame.render_passes.size());
7890 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7893 TEST_F(LayerTreeHostImplTest, RemoveEmptyRenderPass) {
7894 LayerTreeHostImpl::FrameData frame;
7895 frame.render_passes.push_back(RenderPass::Create());
7896 RenderPass* pass3 = frame.render_passes.back();
7897 frame.render_passes.push_back(RenderPass::Create());
7898 RenderPass* pass2 = frame.render_passes.back();
7899 frame.render_passes.push_back(RenderPass::Create());
7900 RenderPass* pass1 = frame.render_passes.back();
7902 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7903 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7904 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7906 frame.render_passes_by_id[pass1->id] = pass1;
7907 frame.render_passes_by_id[pass2->id] = pass2;
7908 frame.render_passes_by_id[pass3->id] = pass3;
7910 // pass1 is not empty, but pass2 and pass3 are.
7911 SolidColorDrawQuad* color_quad;
7912 color_quad = pass1->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
7913 color_quad->material = DrawQuad::SOLID_COLOR;
7915 // pass3 is referenced by pass2.
7916 RenderPassDrawQuad* rpdq =
7917 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7918 rpdq->material = DrawQuad::RENDER_PASS;
7919 rpdq->render_pass_id = pass3->id;
7921 // pass2 is referenced by pass1.
7922 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7923 rpdq->material = DrawQuad::RENDER_PASS;
7924 rpdq->render_pass_id = pass2->id;
7926 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7927 // should be removed.
7928 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7929 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7930 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7931 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7932 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7933 EXPECT_EQ(1u, frame.render_passes.size());
7934 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7935 // The RenderPassDrawQuad should be removed from pass1.
7936 EXPECT_EQ(1u, pass1->quad_list.size());
7937 EXPECT_EQ(DrawQuad::SOLID_COLOR, pass1->quad_list.ElementAt(0)->material);
7940 TEST_F(LayerTreeHostImplTest, DoNotRemoveEmptyRootRenderPass) {
7941 LayerTreeHostImpl::FrameData frame;
7942 frame.render_passes.push_back(RenderPass::Create());
7943 RenderPass* pass3 = frame.render_passes.back();
7944 frame.render_passes.push_back(RenderPass::Create());
7945 RenderPass* pass2 = frame.render_passes.back();
7946 frame.render_passes.push_back(RenderPass::Create());
7947 RenderPass* pass1 = frame.render_passes.back();
7949 pass1->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7950 pass2->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7951 pass3->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7953 frame.render_passes_by_id[pass1->id] = pass1;
7954 frame.render_passes_by_id[pass2->id] = pass2;
7955 frame.render_passes_by_id[pass3->id] = pass3;
7957 // pass3 is referenced by pass2.
7958 RenderPassDrawQuad* rpdq =
7959 pass2->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7960 rpdq->material = DrawQuad::RENDER_PASS;
7961 rpdq->render_pass_id = pass3->id;
7963 // pass2 is referenced by pass1.
7964 rpdq = pass1->CreateAndAppendDrawQuad<RenderPassDrawQuad>();
7965 rpdq->material = DrawQuad::RENDER_PASS;
7966 rpdq->render_pass_id = pass2->id;
7968 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7969 // should be removed. Then pass1 is empty too, but it's the root so it should
7970 // not be removed.
7971 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame);
7972 EXPECT_EQ(1u, frame.render_passes_by_id.size());
7973 EXPECT_TRUE(frame.render_passes_by_id[RenderPassId(1, 0)]);
7974 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(2, 0)]);
7975 EXPECT_FALSE(frame.render_passes_by_id[RenderPassId(3, 0)]);
7976 EXPECT_EQ(1u, frame.render_passes.size());
7977 EXPECT_EQ(RenderPassId(1, 0), frame.render_passes[0]->id);
7978 // The RenderPassDrawQuad should be removed from pass1.
7979 EXPECT_EQ(0u, pass1->quad_list.size());
7982 class FakeVideoFrameController : public VideoFrameController {
7983 public:
7984 void OnBeginFrame(const BeginFrameArgs& args) override {
7985 begin_frame_args_ = args;
7986 did_draw_frame_ = false;
7989 void DidDrawFrame() override { did_draw_frame_ = true; }
7991 const BeginFrameArgs& begin_frame_args() const { return begin_frame_args_; }
7993 bool did_draw_frame() const { return did_draw_frame_; }
7995 private:
7996 BeginFrameArgs begin_frame_args_;
7997 bool did_draw_frame_ = false;
8000 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerInsideFrame) {
8001 host_impl_->DidFinishImplFrame();
8003 BeginFrameArgs begin_frame_args =
8004 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8005 FakeVideoFrameController controller;
8007 host_impl_->WillBeginImplFrame(begin_frame_args);
8008 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8009 host_impl_->AddVideoFrameController(&controller);
8010 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8011 host_impl_->DidFinishImplFrame();
8013 EXPECT_FALSE(controller.did_draw_frame());
8014 LayerTreeHostImpl::FrameData frame;
8015 host_impl_->DidDrawAllLayers(frame);
8016 EXPECT_TRUE(controller.did_draw_frame());
8018 controller.OnBeginFrame(begin_frame_args);
8019 EXPECT_FALSE(controller.did_draw_frame());
8020 host_impl_->RemoveVideoFrameController(&controller);
8021 host_impl_->DidDrawAllLayers(frame);
8022 EXPECT_FALSE(controller.did_draw_frame());
8025 TEST_F(LayerTreeHostImplTest, AddVideoFrameControllerOutsideFrame) {
8026 host_impl_->DidFinishImplFrame();
8028 BeginFrameArgs begin_frame_args =
8029 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8030 FakeVideoFrameController controller;
8032 host_impl_->WillBeginImplFrame(begin_frame_args);
8033 host_impl_->DidFinishImplFrame();
8035 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8036 host_impl_->AddVideoFrameController(&controller);
8037 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8039 begin_frame_args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE);
8040 EXPECT_FALSE(controller.begin_frame_args().IsValid());
8041 host_impl_->WillBeginImplFrame(begin_frame_args);
8042 EXPECT_TRUE(controller.begin_frame_args().IsValid());
8044 EXPECT_FALSE(controller.did_draw_frame());
8045 LayerTreeHostImpl::FrameData frame;
8046 host_impl_->DidDrawAllLayers(frame);
8047 EXPECT_TRUE(controller.did_draw_frame());
8049 controller.OnBeginFrame(begin_frame_args);
8050 EXPECT_FALSE(controller.did_draw_frame());
8051 host_impl_->RemoveVideoFrameController(&controller);
8052 host_impl_->DidDrawAllLayers(frame);
8053 EXPECT_FALSE(controller.did_draw_frame());
8056 TEST_F(LayerTreeHostImplTest, GpuRasterizationStatusModes) {
8057 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8059 host_impl_->SetHasGpuRasterizationTrigger(true);
8060 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8061 EXPECT_EQ(GpuRasterizationStatus::ON, host_impl_->gpu_rasterization_status());
8062 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8064 host_impl_->SetHasGpuRasterizationTrigger(false);
8065 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8066 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT,
8067 host_impl_->gpu_rasterization_status());
8068 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8070 host_impl_->SetHasGpuRasterizationTrigger(true);
8071 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8072 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT,
8073 host_impl_->gpu_rasterization_status());
8074 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8075 EXPECT_FALSE(host_impl_->use_msaa());
8077 scoped_ptr<TestWebGraphicsContext3D> context_with_msaa =
8078 TestWebGraphicsContext3D::Create();
8079 context_with_msaa->SetMaxSamples(8);
8081 LayerTreeSettings msaaSettings = GpuRasterizationEnabledSettings();
8082 msaaSettings.gpu_rasterization_msaa_sample_count = 4;
8083 EXPECT_TRUE(CreateHostImpl(
8084 msaaSettings, FakeOutputSurface::Create3d(context_with_msaa.Pass())));
8085 host_impl_->SetHasGpuRasterizationTrigger(true);
8086 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8087 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT,
8088 host_impl_->gpu_rasterization_status());
8089 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8090 EXPECT_TRUE(host_impl_->use_msaa());
8092 LayerTreeSettings settings = DefaultSettings();
8093 settings.gpu_rasterization_enabled = false;
8094 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8095 host_impl_->SetHasGpuRasterizationTrigger(true);
8096 host_impl_->SetContentIsSuitableForGpuRasterization(true);
8097 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE,
8098 host_impl_->gpu_rasterization_status());
8099 EXPECT_FALSE(host_impl_->use_gpu_rasterization());
8101 settings.gpu_rasterization_forced = true;
8102 EXPECT_TRUE(CreateHostImpl(settings, FakeOutputSurface::Create3d()));
8104 host_impl_->SetHasGpuRasterizationTrigger(false);
8105 host_impl_->SetContentIsSuitableForGpuRasterization(false);
8106 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED,
8107 host_impl_->gpu_rasterization_status());
8108 EXPECT_TRUE(host_impl_->use_gpu_rasterization());
8111 // A mock output surface which lets us detect calls to ForceReclaimResources.
8112 class MockReclaimResourcesOutputSurface : public FakeOutputSurface {
8113 public:
8114 static scoped_ptr<MockReclaimResourcesOutputSurface> Create3d() {
8115 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8116 TestContextProvider::Create(), TestContextProvider::Create(), false));
8119 MOCK_METHOD0(ForceReclaimResources, void());
8121 protected:
8122 MockReclaimResourcesOutputSurface(
8123 scoped_refptr<ContextProvider> context_provider,
8124 scoped_refptr<ContextProvider> worker_context_provider,
8125 bool delegated_rendering)
8126 : FakeOutputSurface(context_provider,
8127 worker_context_provider,
8128 delegated_rendering) {}
8131 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8132 // being reclaimed to block drawing between BeginCommit / Swap. This test
8133 // ensures that BeginCommit triggers ForceReclaimResources. See
8134 // crbug.com/489515.
8135 TEST_F(LayerTreeHostImplTest, BeginCommitReclaimsResources) {
8136 scoped_ptr<MockReclaimResourcesOutputSurface> output_surface(
8137 MockReclaimResourcesOutputSurface::Create3d());
8138 // Hold an unowned pointer to the output surface to use for mock expectations.
8139 MockReclaimResourcesOutputSurface* mock_output_surface = output_surface.get();
8141 CreateHostImpl(DefaultSettings(), output_surface.Pass());
8142 EXPECT_CALL(*mock_output_surface, ForceReclaimResources()).Times(1);
8143 host_impl_->BeginCommit();
8146 } // namespace
8147 } // namespace cc