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"
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/test_gpu_memory_buffer_manager.h"
57 #include "cc/test/test_shared_bitmap_manager.h"
58 #include "cc/test/test_task_graph_runner.h"
59 #include "cc/test/test_web_graphics_context_3d.h"
60 #include "cc/trees/layer_tree_impl.h"
61 #include "cc/trees/single_thread_proxy.h"
62 #include "media/base/media.h"
63 #include "testing/gmock/include/gmock/gmock.h"
64 #include "testing/gtest/include/gtest/gtest.h"
65 #include "third_party/skia/include/core/SkMallocPixelRef.h"
66 #include "ui/gfx/geometry/rect_conversions.h"
67 #include "ui/gfx/geometry/size_conversions.h"
68 #include "ui/gfx/geometry/vector2d_conversions.h"
70 using ::testing::Mock
;
71 using ::testing::Return
;
72 using ::testing::AnyNumber
;
73 using ::testing::AtLeast
;
75 using media::VideoFrame
;
80 class LayerTreeHostImplTest
: public testing::Test
,
81 public LayerTreeHostImplClient
{
83 LayerTreeHostImplTest()
84 : proxy_(base::ThreadTaskRunnerHandle::Get(),
85 base::ThreadTaskRunnerHandle::Get()),
86 always_impl_thread_(&proxy_
),
87 always_main_thread_blocked_(&proxy_
),
88 on_can_draw_state_changed_called_(false),
89 did_notify_ready_to_activate_(false),
90 did_request_commit_(false),
91 did_request_redraw_(false),
92 did_request_animate_(false),
93 did_request_prepare_tiles_(false),
94 did_complete_page_scale_animation_(false),
95 reduce_memory_result_(true) {
96 media::InitializeMediaLibrary();
99 LayerTreeSettings
DefaultSettings() {
100 LayerTreeSettings settings
;
101 settings
.minimum_occlusion_tracking_size
= gfx::Size();
102 settings
.renderer_settings
.texture_id_allocation_chunk_size
= 1;
103 settings
.gpu_rasterization_enabled
= true;
107 void SetUp() override
{
108 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
111 void TearDown() override
{}
113 void UpdateRendererCapabilitiesOnImplThread() override
{}
114 void DidLoseOutputSurfaceOnImplThread() override
{}
115 void CommitVSyncParameters(base::TimeTicks timebase
,
116 base::TimeDelta interval
) override
{}
117 void SetEstimatedParentDrawTime(base::TimeDelta draw_time
) override
{}
118 void SetMaxSwapsPendingOnImplThread(int max
) override
{}
119 void DidSwapBuffersOnImplThread() override
{}
120 void DidSwapBuffersCompleteOnImplThread() override
{}
121 void OnCanDrawStateChanged(bool can_draw
) override
{
122 on_can_draw_state_changed_called_
= true;
124 void NotifyReadyToActivate() override
{
125 did_notify_ready_to_activate_
= true;
126 host_impl_
->ActivateSyncTree();
128 void NotifyReadyToDraw() override
{}
129 void SetNeedsRedrawOnImplThread() override
{ did_request_redraw_
= true; }
130 void SetNeedsRedrawRectOnImplThread(const gfx::Rect
& damage_rect
) override
{
131 did_request_redraw_
= true;
133 void SetNeedsAnimateOnImplThread() override
{ did_request_animate_
= true; }
134 void SetNeedsPrepareTilesOnImplThread() override
{
135 did_request_prepare_tiles_
= true;
137 void SetNeedsCommitOnImplThread() override
{ did_request_commit_
= true; }
138 void SetVideoNeedsBeginFrames(bool needs_begin_frames
) override
{}
139 void PostAnimationEventsToMainThreadOnImplThread(
140 scoped_ptr
<AnimationEventsVector
> events
) override
{}
141 bool IsInsideDraw() override
{ return false; }
142 void RenewTreePriority() override
{}
143 void PostDelayedAnimationTaskOnImplThread(const base::Closure
& task
,
144 base::TimeDelta delay
) override
{
145 animation_task_
= task
;
146 requested_animation_delay_
= delay
;
148 void DidActivateSyncTree() override
{}
149 void WillPrepareTiles() override
{}
150 void DidPrepareTiles() override
{}
151 void DidCompletePageScaleAnimationOnImplThread() override
{
152 did_complete_page_scale_animation_
= true;
154 void OnDrawForOutputSurface() override
{}
155 void PostFrameTimingEventsOnImplThread(
156 scoped_ptr
<FrameTimingTracker::CompositeTimingSet
> composite_events
,
157 scoped_ptr
<FrameTimingTracker::MainFrameTimingSet
> main_frame_events
)
160 void set_reduce_memory_result(bool reduce_memory_result
) {
161 reduce_memory_result_
= reduce_memory_result
;
164 virtual bool CreateHostImpl(const LayerTreeSettings
& settings
,
165 scoped_ptr
<OutputSurface
> output_surface
) {
166 host_impl_
= LayerTreeHostImpl::Create(
167 settings
, this, &proxy_
, &stats_instrumentation_
,
168 &shared_bitmap_manager_
, &gpu_memory_buffer_manager_
,
169 &task_graph_runner_
, 0);
170 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
171 host_impl_
->SetViewportSize(gfx::Size(10, 10));
172 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
173 // Set the BeginFrameArgs so that methods which use it are able to.
174 host_impl_
->WillBeginImplFrame(CreateBeginFrameArgsForTesting(
175 BEGINFRAME_FROM_HERE
,
176 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1)));
177 host_impl_
->DidFinishImplFrame();
181 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
182 root
->SetPosition(gfx::PointF());
183 root
->SetBounds(gfx::Size(10, 10));
184 root
->SetDrawsContent(true);
185 root
->draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
186 root
->SetHasRenderSurface(true);
187 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
190 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
191 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
192 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
193 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
196 static ::testing::AssertionResult
ScrollInfoContains(
197 const ScrollAndScaleSet
& scroll_info
,
199 const gfx::Vector2d
& scroll_delta
) {
200 int times_encountered
= 0;
202 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
203 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
206 if (scroll_delta
!= scroll_info
.scrolls
[i
].scroll_delta
) {
207 return ::testing::AssertionFailure()
208 << "Expected " << scroll_delta
.ToString() << ", not "
209 << scroll_info
.scrolls
[i
].scroll_delta
.ToString();
214 if (times_encountered
!= 1)
215 return ::testing::AssertionFailure() << "No layer found with id " << id
;
216 return ::testing::AssertionSuccess();
219 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
220 int times_encountered
= 0;
222 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
223 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
228 ASSERT_EQ(0, times_encountered
);
231 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
232 const gfx::Size
& content_size
) {
233 // Create both an inner viewport scroll layer and an outer viewport scroll
234 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
235 // 0x0, so the scrolls will be applied directly to the inner viewport.
236 const int kOuterViewportClipLayerId
= 116;
237 const int kOuterViewportScrollLayerId
= 117;
238 const int kContentLayerId
= 118;
239 const int kInnerViewportScrollLayerId
= 2;
240 const int kInnerViewportClipLayerId
= 4;
241 const int kPageScaleLayerId
= 5;
243 scoped_ptr
<LayerImpl
> root
=
244 LayerImpl::Create(layer_tree_impl
, 1);
245 root
->SetBounds(content_size
);
246 root
->SetPosition(gfx::PointF());
247 root
->SetHasRenderSurface(true);
249 scoped_ptr
<LayerImpl
> inner_scroll
=
250 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
251 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
252 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
254 scoped_ptr
<LayerImpl
> inner_clip
=
255 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
256 inner_clip
->SetBounds(
257 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
259 scoped_ptr
<LayerImpl
> page_scale
=
260 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
262 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
263 inner_scroll
->SetBounds(content_size
);
264 inner_scroll
->SetPosition(gfx::PointF());
266 scoped_ptr
<LayerImpl
> outer_clip
=
267 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
268 outer_clip
->SetBounds(content_size
);
269 outer_clip
->SetIsContainerForFixedPositionLayers(true);
271 scoped_ptr
<LayerImpl
> outer_scroll
=
272 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
273 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
274 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
275 outer_scroll
->SetBounds(content_size
);
276 outer_scroll
->SetPosition(gfx::PointF());
278 scoped_ptr
<LayerImpl
> contents
=
279 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
280 contents
->SetDrawsContent(true);
281 contents
->SetBounds(content_size
);
282 contents
->SetPosition(gfx::PointF());
284 outer_scroll
->AddChild(contents
.Pass());
285 outer_clip
->AddChild(outer_scroll
.Pass());
286 inner_scroll
->AddChild(outer_clip
.Pass());
287 page_scale
->AddChild(inner_scroll
.Pass());
288 inner_clip
->AddChild(page_scale
.Pass());
289 root
->AddChild(inner_clip
.Pass());
291 layer_tree_impl
->SetRootLayer(root
.Pass());
292 layer_tree_impl
->SetViewportLayersFromIds(
293 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
294 kOuterViewportScrollLayerId
);
296 layer_tree_impl
->DidBecomeActive();
297 return layer_tree_impl
->InnerViewportScrollLayer();
300 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
301 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
302 host_impl_
->active_tree(), content_size
);
303 host_impl_
->active_tree()->DidBecomeActive();
307 // Sets up a typical virtual viewport setup with one child content layer.
308 // Returns a pointer to the content layer.
309 LayerImpl
* CreateBasicVirtualViewportLayers(const gfx::Size
& viewport_size
,
310 const gfx::Size
& content_size
) {
311 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
312 // the inner a different size from the outer. We'll reuse its layer
313 // hierarchy but adjust the sizing to our needs.
314 CreateScrollAndContentsLayers(host_impl_
->active_tree(), content_size
);
316 LayerImpl
* content_layer
=
317 host_impl_
->OuterViewportScrollLayer()->children().back();
318 content_layer
->SetBounds(content_size
);
319 host_impl_
->OuterViewportScrollLayer()->SetBounds(content_size
);
321 LayerImpl
* outer_clip
= host_impl_
->OuterViewportScrollLayer()->parent();
322 outer_clip
->SetBounds(viewport_size
);
324 LayerImpl
* inner_clip_layer
=
325 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
326 inner_clip_layer
->SetBounds(viewport_size
);
327 host_impl_
->InnerViewportScrollLayer()->SetBounds(viewport_size
);
329 host_impl_
->SetViewportSize(viewport_size
);
330 host_impl_
->active_tree()->DidBecomeActive();
332 return content_layer
;
335 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
336 const gfx::Size
& size
,
337 LayerImpl
* clip_layer
) {
339 DCHECK(id
!= clip_layer
->id());
340 scoped_ptr
<LayerImpl
> layer
=
341 LayerImpl::Create(host_impl_
->active_tree(), id
);
342 layer
->SetScrollClipLayer(clip_layer
->id());
343 layer
->SetDrawsContent(true);
344 layer
->SetBounds(size
);
345 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
350 LayerTreeHostImpl::FrameData frame
;
351 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
352 host_impl_
->DrawLayers(&frame
);
353 host_impl_
->DidDrawAllLayers(frame
);
356 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
357 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
358 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
359 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
360 float device_scale_factor
);
362 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
363 // Note: It is not possible to disable the renderer once it has been set,
364 // so we do not need to test that disabling the renderer notifies us
365 // that can_draw changed.
366 EXPECT_FALSE(host_impl_
->CanDraw());
367 on_can_draw_state_changed_called_
= false;
369 // Set up the root layer, which allows us to draw.
370 SetupScrollAndContentsLayers(gfx::Size(100, 100));
371 EXPECT_TRUE(host_impl_
->CanDraw());
372 EXPECT_TRUE(on_can_draw_state_changed_called_
);
373 on_can_draw_state_changed_called_
= false;
375 // Toggle the root layer to make sure it toggles can_draw
376 host_impl_
->active_tree()->SetRootLayer(nullptr);
377 EXPECT_FALSE(host_impl_
->CanDraw());
378 EXPECT_TRUE(on_can_draw_state_changed_called_
);
379 on_can_draw_state_changed_called_
= false;
381 SetupScrollAndContentsLayers(gfx::Size(100, 100));
382 EXPECT_TRUE(host_impl_
->CanDraw());
383 EXPECT_TRUE(on_can_draw_state_changed_called_
);
384 on_can_draw_state_changed_called_
= false;
386 // Toggle the device viewport size to make sure it toggles can_draw.
387 host_impl_
->SetViewportSize(gfx::Size());
389 EXPECT_TRUE(host_impl_
->CanDraw());
391 EXPECT_FALSE(host_impl_
->CanDraw());
393 EXPECT_TRUE(on_can_draw_state_changed_called_
);
394 on_can_draw_state_changed_called_
= false;
396 host_impl_
->SetViewportSize(gfx::Size(100, 100));
397 EXPECT_TRUE(host_impl_
->CanDraw());
398 EXPECT_TRUE(on_can_draw_state_changed_called_
);
399 on_can_draw_state_changed_called_
= false;
402 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
405 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
406 return FakeOutputSurface::Create3d();
409 void DrawOneFrame() {
410 LayerTreeHostImpl::FrameData frame_data
;
411 host_impl_
->PrepareToDraw(&frame_data
);
412 host_impl_
->DidDrawAllLayers(frame_data
);
416 DebugScopedSetImplThread always_impl_thread_
;
417 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
419 TestSharedBitmapManager shared_bitmap_manager_
;
420 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
421 TestTaskGraphRunner task_graph_runner_
;
422 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
423 FakeRenderingStatsInstrumentation stats_instrumentation_
;
424 bool on_can_draw_state_changed_called_
;
425 bool did_notify_ready_to_activate_
;
426 bool did_request_commit_
;
427 bool did_request_redraw_
;
428 bool did_request_animate_
;
429 bool did_request_prepare_tiles_
;
430 bool did_complete_page_scale_animation_
;
431 bool reduce_memory_result_
;
432 base::Closure animation_task_
;
433 base::TimeDelta requested_animation_delay_
;
436 // A test fixture for new animation timelines tests.
437 class LayerTreeHostImplTimelinesTest
: public LayerTreeHostImplTest
{
439 void SetUp() override
{
440 LayerTreeSettings settings
= DefaultSettings();
441 settings
.use_compositor_animation_timelines
= true;
442 CreateHostImpl(settings
, CreateOutputSurface());
446 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
447 bool always_draw
= false;
448 CheckNotifyCalledIfCanDrawChanged(always_draw
);
451 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
452 CreateHostImpl(DefaultSettings(),
453 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
455 bool always_draw
= true;
456 CheckNotifyCalledIfCanDrawChanged(always_draw
);
459 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
460 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
462 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
463 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
466 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
468 scoped_ptr
<LayerImpl
> root
=
469 LayerImpl::Create(host_impl_
->active_tree(), 1);
470 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
471 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
472 root
->children()[1]->AddChild(
473 LayerImpl::Create(host_impl_
->active_tree(), 4));
474 root
->children()[1]->AddChild(
475 LayerImpl::Create(host_impl_
->active_tree(), 5));
476 root
->children()[1]->children()[0]->AddChild(
477 LayerImpl::Create(host_impl_
->active_tree(), 6));
478 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
480 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
482 ExpectClearedScrollDeltasRecursive(root
);
484 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
486 scroll_info
= host_impl_
->ProcessScrollDeltas();
487 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
488 ExpectClearedScrollDeltasRecursive(root
);
490 scroll_info
= host_impl_
->ProcessScrollDeltas();
491 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
492 ExpectClearedScrollDeltasRecursive(root
);
495 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
496 gfx::ScrollOffset
scroll_offset(20, 30);
497 gfx::Vector2d
scroll_delta(11, -15);
499 scoped_ptr
<LayerImpl
> root_clip
=
500 LayerImpl::Create(host_impl_
->active_tree(), 2);
501 scoped_ptr
<LayerImpl
> root
=
502 LayerImpl::Create(host_impl_
->active_tree(), 1);
503 root_clip
->SetBounds(gfx::Size(10, 10));
504 LayerImpl
* root_layer
= root
.get();
505 root_clip
->AddChild(root
.Pass());
506 root_layer
->SetBounds(gfx::Size(110, 110));
507 root_layer
->SetScrollClipLayer(root_clip
->id());
508 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
509 root_layer
->ScrollBy(scroll_delta
);
510 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
512 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
514 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
516 scroll_info
= host_impl_
->ProcessScrollDeltas();
517 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
518 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(), scroll_delta
));
520 gfx::Vector2d
scroll_delta2(-5, 27);
521 root
->ScrollBy(scroll_delta2
);
522 scroll_info
= host_impl_
->ProcessScrollDeltas();
523 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
524 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
525 scroll_delta
+ scroll_delta2
));
527 root
->ScrollBy(gfx::Vector2d());
528 scroll_info
= host_impl_
->ProcessScrollDeltas();
529 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
530 scroll_delta
+ scroll_delta2
));
533 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
534 SetupScrollAndContentsLayers(gfx::Size(100, 100));
535 host_impl_
->SetViewportSize(gfx::Size(50, 50));
538 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
539 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
540 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
541 InputHandler::WHEEL
));
542 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
543 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
544 InputHandler::WHEEL
));
545 host_impl_
->ScrollEnd();
546 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
547 InputHandler::WHEEL
));
548 EXPECT_TRUE(did_request_redraw_
);
549 EXPECT_TRUE(did_request_commit_
);
552 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
553 SetupScrollAndContentsLayers(gfx::Size(100, 100));
554 host_impl_
->SetViewportSize(gfx::Size(50, 50));
557 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
558 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
559 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
560 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
561 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
562 host_impl_
->ScrollEnd();
563 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
566 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
567 // We should not crash when trying to scroll an empty layer tree.
568 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
569 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
572 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
573 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
574 TestWebGraphicsContext3D::Create();
575 context_owned
->set_context_lost(true);
577 // Initialization will fail.
578 EXPECT_FALSE(CreateHostImpl(
579 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
581 SetupScrollAndContentsLayers(gfx::Size(100, 100));
583 // We should not crash when trying to scroll after the renderer initialization
585 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
586 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
589 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
590 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
591 host_impl_
->SetViewportSize(gfx::Size(50, 50));
594 // We should not crash if the tree is replaced while we are scrolling.
595 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
596 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
597 host_impl_
->active_tree()->DetachLayerTree();
599 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
601 // We should still be scrolling, because the scrolled layer also exists in the
603 gfx::Vector2d
scroll_delta(0, 10);
604 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
605 host_impl_
->ScrollEnd();
606 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
608 ScrollInfoContains(*scroll_info
, scroll_layer
->id(), scroll_delta
));
611 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
612 SetupScrollAndContentsLayers(gfx::Size(100, 100));
613 host_impl_
->SetViewportSize(gfx::Size(50, 50));
615 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
617 // With registered event handlers, wheel scrolls don't necessarily
618 // have to go to the main thread.
619 root
->SetHaveWheelEventHandlers(true);
620 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
621 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
622 host_impl_
->ScrollEnd();
624 // But typically the scroll-blocks-on mode will require them to.
625 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
626 SCROLL_BLOCKS_ON_START_TOUCH
);
627 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
628 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
630 // But gesture scrolls can still be handled.
631 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
632 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
633 host_impl_
->ScrollEnd();
635 // And if the handlers go away, wheel scrolls can again be processed
636 // on impl (despite the scroll-blocks-on mode).
637 root
->SetHaveWheelEventHandlers(false);
638 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
639 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
640 host_impl_
->ScrollEnd();
643 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
644 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
645 host_impl_
->SetViewportSize(gfx::Size(50, 50));
647 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
649 LayerImpl
* child
= 0;
651 scoped_ptr
<LayerImpl
> child_layer
=
652 LayerImpl::Create(host_impl_
->active_tree(), 6);
653 child
= child_layer
.get();
654 child_layer
->SetDrawsContent(true);
655 child_layer
->SetPosition(gfx::PointF(0, 20));
656 child_layer
->SetBounds(gfx::Size(50, 50));
657 scroll
->AddChild(child_layer
.Pass());
660 // Touch handler regions determine whether touch events block scroll.
661 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
662 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
663 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
664 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
665 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
667 // But they don't influence the actual handling of the scroll gestures.
668 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
669 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
670 host_impl_
->ScrollEnd();
672 // It's the union of scroll-blocks-on mode bits across all layers in the
673 // scroll paret chain that matters.
674 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
675 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
676 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
677 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
678 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
681 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
682 SetupScrollAndContentsLayers(gfx::Size(100, 100));
683 host_impl_
->SetViewportSize(gfx::Size(50, 50));
685 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
687 // With registered scroll handlers, scrolls don't generally have to go
688 // to the main thread.
689 root
->SetHaveScrollEventHandlers(true);
690 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
691 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
692 host_impl_
->ScrollEnd();
694 // Even the default scroll blocks on mode doesn't require this.
695 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
696 SCROLL_BLOCKS_ON_START_TOUCH
);
697 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
698 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
699 host_impl_
->ScrollEnd();
701 // But the page can opt in to blocking on scroll event handlers.
702 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
703 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
704 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
706 // GESTURE and WHEEL scrolls behave identically in this regard.
707 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
708 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
710 // And if the handlers go away, scrolls can again be processed on impl
711 // (despite the scroll-blocks-on mode).
712 root
->SetHaveScrollEventHandlers(false);
713 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
714 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
715 host_impl_
->ScrollEnd();
718 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
719 host_impl_
->SetViewportSize(gfx::Size(50, 50));
721 // Create a normal scrollable root layer
722 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
723 LayerImpl
* root_child
= root_scroll
->children()[0];
724 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
727 // Create two child scrollable layers
728 LayerImpl
* child1
= 0;
730 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
731 LayerImpl::Create(host_impl_
->active_tree(), 6);
732 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
733 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
734 child1
= scrollable_child_1
.get();
735 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
736 scrollable_child_1
->SetHaveWheelEventHandlers(true);
737 scrollable_child_1
->SetHaveScrollEventHandlers(true);
738 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
739 root_child
->AddChild(scrollable_child_clip_1
.Pass());
742 LayerImpl
* child2
= 0;
744 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
745 LayerImpl::Create(host_impl_
->active_tree(), 8);
746 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
747 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
748 child2
= scrollable_child_2
.get();
749 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
750 scrollable_child_2
->SetHaveWheelEventHandlers(true);
751 scrollable_child_2
->SetHaveScrollEventHandlers(true);
752 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
753 root_child
->AddChild(scrollable_child_clip_2
.Pass());
756 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
757 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
758 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
759 host_impl_
->ScrollEnd();
760 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
761 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
762 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
764 // But not those that hit only other layers.
765 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
766 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
767 host_impl_
->ScrollEnd();
769 // It's the union of bits set across the scroll ancestor chain that matters.
770 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
771 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
772 host_impl_
->ScrollEnd();
773 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
774 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
775 host_impl_
->ScrollEnd();
776 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
777 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
778 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
779 host_impl_
->ScrollEnd();
780 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
781 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
782 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
783 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
784 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
785 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
786 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
789 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
790 SetupScrollAndContentsLayers(gfx::Size(100, 100));
791 host_impl_
->SetViewportSize(gfx::Size(50, 50));
794 // Ignore the fling since no layer is being scrolled
795 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
797 // Start scrolling a layer
798 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
799 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
801 // Now the fling should go ahead since we've started scrolling a layer
802 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
805 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
806 SetupScrollAndContentsLayers(gfx::Size(100, 100));
807 host_impl_
->SetViewportSize(gfx::Size(50, 50));
810 // Ignore the fling since no layer is being scrolled
811 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
813 // Start scrolling a layer
814 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
815 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
817 // Now the fling should go ahead since we've started scrolling a layer
818 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
821 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
822 SetupScrollAndContentsLayers(gfx::Size(100, 100));
823 host_impl_
->SetViewportSize(gfx::Size(50, 50));
825 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
827 root
->SetShouldScrollOnMainThread(true);
829 // Start scrolling a layer
830 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
831 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
833 // The fling should be ignored since there's no layer being scrolled impl-side
834 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
837 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
838 SetupScrollAndContentsLayers(gfx::Size(100, 100));
839 host_impl_
->SetViewportSize(gfx::Size(50, 50));
841 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
843 root
->SetShouldScrollOnMainThread(true);
845 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
846 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
847 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
848 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
851 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
852 SetupScrollAndContentsLayers(gfx::Size(200, 200));
853 host_impl_
->SetViewportSize(gfx::Size(100, 100));
855 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
856 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
860 // All scroll types inside the non-fast scrollable region should fail.
861 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
862 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
863 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
864 InputHandler::WHEEL
));
865 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
866 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
867 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
868 InputHandler::GESTURE
));
870 // All scroll types outside this region should succeed.
871 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
872 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
873 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
874 InputHandler::GESTURE
));
875 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
876 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
877 InputHandler::GESTURE
));
878 host_impl_
->ScrollEnd();
879 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
880 InputHandler::GESTURE
));
881 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
882 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
883 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
884 InputHandler::GESTURE
));
885 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
886 host_impl_
->ScrollEnd();
887 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
888 InputHandler::GESTURE
));
891 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
892 SetupScrollAndContentsLayers(gfx::Size(200, 200));
893 host_impl_
->SetViewportSize(gfx::Size(100, 100));
895 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
896 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
897 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
901 // This point would fall into the non-fast scrollable region except that we've
902 // moved the layer down by 25 pixels.
903 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
904 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
905 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
906 InputHandler::WHEEL
));
907 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
908 host_impl_
->ScrollEnd();
910 // This point is still inside the non-fast region.
911 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
912 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
915 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
916 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
917 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
918 host_impl_
->SetViewportSize(gfx::Size(50, 50));
921 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
922 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
923 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
924 host_impl_
->ScrollEnd();
925 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
928 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
929 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
930 scroll_layer
->SetHaveScrollEventHandlers(true);
931 host_impl_
->SetViewportSize(gfx::Size(50, 50));
934 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
935 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
936 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
937 host_impl_
->ScrollEnd();
938 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
941 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
942 SetupScrollAndContentsLayers(gfx::Size(200, 200));
943 host_impl_
->SetViewportSize(gfx::Size(100, 100));
947 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
948 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
950 // Trying to scroll to the left/top will not succeed.
952 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
954 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
956 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
958 // Scrolling to the right/bottom will succeed.
960 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
962 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
964 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
966 // Scrolling to left/top will now succeed.
968 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
970 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
972 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
974 // Scrolling diagonally against an edge will succeed.
976 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
978 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
980 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
982 // Trying to scroll more than the available space will also succeed.
984 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
987 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
988 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
989 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
993 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
994 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
996 // Trying to scroll without a vertical scrollbar will fail.
997 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
998 gfx::Point(), SCROLL_FORWARD
));
999 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
1000 gfx::Point(), SCROLL_BACKWARD
));
1002 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
1003 PaintedScrollbarLayerImpl::Create(
1004 host_impl_
->active_tree(),
1007 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1008 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1009 vertical_scrollbar
.get());
1011 // Trying to scroll with a vertical scrollbar will succeed.
1012 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1013 gfx::Point(), SCROLL_FORWARD
));
1014 EXPECT_FLOAT_EQ(875.f
,
1015 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1016 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1017 gfx::Point(), SCROLL_BACKWARD
));
1020 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1021 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1022 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1024 gfx::Size
overflow_size(400, 400);
1025 ASSERT_EQ(1u, scroll_layer
->children().size());
1026 LayerImpl
* overflow
= scroll_layer
->children()[0];
1027 overflow
->SetBounds(overflow_size
);
1028 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1029 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1030 overflow
->SetPosition(gfx::PointF());
1033 gfx::Point
scroll_position(10, 10);
1035 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1036 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1037 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1038 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1040 gfx::Vector2dF
scroll_delta(10, 10);
1041 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1042 host_impl_
->ScrollEnd();
1043 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1044 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1046 overflow
->set_user_scrollable_horizontal(false);
1048 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1049 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1050 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1053 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1054 host_impl_
->ScrollEnd();
1055 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1056 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1058 overflow
->set_user_scrollable_vertical(false);
1060 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1061 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1062 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1063 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1065 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1066 host_impl_
->ScrollEnd();
1067 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1068 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1071 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1072 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1073 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1076 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1077 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1078 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1080 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1081 float page_scale_factor
= 1.f
;
1083 // The impl-based pinch zoom should adjust the max scroll position.
1085 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1086 page_scale_factor
, min_page_scale
, max_page_scale
);
1087 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1088 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1090 float page_scale_delta
= 2.f
;
1092 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1093 host_impl_
->PinchGestureBegin();
1094 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1095 host_impl_
->PinchGestureEnd();
1096 host_impl_
->ScrollEnd();
1097 EXPECT_FALSE(did_request_animate_
);
1098 EXPECT_TRUE(did_request_redraw_
);
1099 EXPECT_TRUE(did_request_commit_
);
1100 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1102 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1103 host_impl_
->ProcessScrollDeltas();
1104 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1106 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1107 scroll_layer
->MaxScrollOffset().ToString());
1110 // Scrolling after a pinch gesture should always be in local space. The
1111 // scroll deltas have the page scale factor applied.
1113 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1114 page_scale_factor
, min_page_scale
, max_page_scale
);
1115 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1116 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1118 float page_scale_delta
= 2.f
;
1119 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1120 host_impl_
->PinchGestureBegin();
1121 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1122 host_impl_
->PinchGestureEnd();
1123 host_impl_
->ScrollEnd();
1125 gfx::Vector2d
scroll_delta(0, 10);
1126 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1127 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1128 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1129 host_impl_
->ScrollEnd();
1131 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1132 host_impl_
->ProcessScrollDeltas();
1133 EXPECT_TRUE(ScrollInfoContains(
1134 *scroll_info
.get(), scroll_layer
->id(),
1135 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
)));
1139 TEST_F(LayerTreeHostImplTest
, ViewportScrollOrder
) {
1140 LayerTreeSettings settings
= DefaultSettings();
1141 settings
.invert_viewport_scroll_order
= true;
1142 CreateHostImpl(settings
,
1143 CreateOutputSurface());
1144 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.25f
, 4.f
);
1146 const gfx::Size
content_size(1000, 1000);
1147 const gfx::Size
viewport_size(500, 500);
1148 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1150 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1151 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1154 gfx::Vector2dF(500, 500),
1155 outer_scroll_layer
->MaxScrollOffset());
1157 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1158 host_impl_
->PinchGestureBegin();
1159 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1160 host_impl_
->PinchGestureEnd();
1161 host_impl_
->ScrollEnd();
1163 // Sanity check - we're zoomed in, starting from the origin.
1165 gfx::Vector2dF(0, 0),
1166 outer_scroll_layer
->CurrentScrollOffset());
1168 gfx::Vector2dF(0, 0),
1169 inner_scroll_layer
->CurrentScrollOffset());
1171 // Scroll down - only the inner viewport should scroll.
1172 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1173 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1174 host_impl_
->ScrollEnd();
1177 gfx::Vector2dF(50, 50),
1178 inner_scroll_layer
->CurrentScrollOffset());
1180 gfx::Vector2dF(0, 0),
1181 outer_scroll_layer
->CurrentScrollOffset());
1183 // Scroll down - outer viewport should start scrolling after the inner is at
1185 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1186 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f
, 1000.f
));
1187 host_impl_
->ScrollEnd();
1190 gfx::Vector2dF(250, 250),
1191 inner_scroll_layer
->CurrentScrollOffset());
1193 gfx::Vector2dF(300, 300),
1194 outer_scroll_layer
->CurrentScrollOffset());
1197 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1198 // as expected. That is, scrolling during a pinch should bubble from the inner
1199 // to the outer viewport.
1200 TEST_F(LayerTreeHostImplTest
, ScrollDuringPinchGesture
) {
1201 LayerTreeSettings settings
= DefaultSettings();
1202 settings
.invert_viewport_scroll_order
= true;
1203 CreateHostImpl(settings
,
1204 CreateOutputSurface());
1205 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1207 const gfx::Size
content_size(1000, 1000);
1208 const gfx::Size
viewport_size(500, 500);
1209 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1211 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1212 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1215 gfx::Vector2dF(500, 500),
1216 outer_scroll_layer
->MaxScrollOffset());
1218 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1219 host_impl_
->PinchGestureBegin();
1221 host_impl_
->PinchGestureUpdate(2, gfx::Point(250, 250));
1223 gfx::Vector2dF(0, 0),
1224 outer_scroll_layer
->CurrentScrollOffset());
1226 gfx::Vector2dF(125, 125),
1227 inner_scroll_layer
->CurrentScrollOffset());
1229 // Needed so that the pinch is accounted for in draw properties.
1232 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f
, 10.f
));
1234 gfx::Vector2dF(0, 0),
1235 outer_scroll_layer
->CurrentScrollOffset());
1237 gfx::Vector2dF(130, 130),
1238 inner_scroll_layer
->CurrentScrollOffset());
1242 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f
, 400.f
));
1244 gfx::Vector2dF(80, 80),
1245 outer_scroll_layer
->CurrentScrollOffset());
1247 gfx::Vector2dF(250, 250),
1248 inner_scroll_layer
->CurrentScrollOffset());
1250 host_impl_
->PinchGestureEnd();
1251 host_impl_
->ScrollEnd();
1254 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1255 // a pinch zoom is anchored within a certain margin of the screen edge, we
1256 // should assume the user means to scroll into the edge of the screen.
1257 TEST_F(LayerTreeHostImplTest
, PinchZoomSnapsToScreenEdge
) {
1258 LayerTreeSettings settings
= DefaultSettings();
1259 settings
.invert_viewport_scroll_order
= true;
1260 CreateHostImpl(settings
,
1261 CreateOutputSurface());
1262 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1264 const gfx::Size
content_size(1000, 1000);
1265 const gfx::Size
viewport_size(500, 500);
1266 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1268 int offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
- 5;
1269 gfx::Point
anchor(viewport_size
.width() - offsetFromEdge
,
1270 viewport_size
.height() - offsetFromEdge
);
1272 // Pinch in within the margins. The scroll should stay exactly locked to the
1273 // bottom and right.
1274 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1275 host_impl_
->PinchGestureBegin();
1276 host_impl_
->PinchGestureUpdate(2, anchor
);
1277 host_impl_
->PinchGestureEnd();
1278 host_impl_
->ScrollEnd();
1281 gfx::Vector2dF(250, 250),
1282 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1285 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1286 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1287 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1289 // Pinch in within the margins. The scroll should stay exactly locked to the
1291 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1292 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1293 host_impl_
->PinchGestureBegin();
1294 host_impl_
->PinchGestureUpdate(2, anchor
);
1295 host_impl_
->PinchGestureEnd();
1296 host_impl_
->ScrollEnd();
1299 gfx::Vector2dF(0, 0),
1300 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1303 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1304 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1305 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1307 // Pinch in just outside the margin. There should be no snapping.
1308 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1309 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1310 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1311 host_impl_
->PinchGestureBegin();
1312 host_impl_
->PinchGestureUpdate(2, anchor
);
1313 host_impl_
->PinchGestureEnd();
1314 host_impl_
->ScrollEnd();
1317 gfx::Vector2dF(50, 50),
1318 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1321 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1322 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1323 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1325 // Pinch in just outside the margin. There should be no snapping.
1326 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1327 anchor
= gfx::Point(viewport_size
.width() - offsetFromEdge
,
1328 viewport_size
.height() - offsetFromEdge
);
1329 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1330 host_impl_
->PinchGestureBegin();
1331 host_impl_
->PinchGestureUpdate(2, anchor
);
1332 host_impl_
->PinchGestureEnd();
1333 host_impl_
->ScrollEnd();
1336 gfx::Vector2dF(200, 200),
1337 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1340 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1341 const gfx::Size
content_size(200, 200);
1342 const gfx::Size
viewport_size(100, 100);
1343 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1345 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1346 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1348 // Zoom into the page by a 2X factor
1349 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1350 float page_scale_factor
= 2.f
;
1351 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1352 page_scale_factor
, min_page_scale
, max_page_scale
);
1353 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1355 // Scroll by a small amount, there should be no bubbling up to the inner
1357 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1358 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1359 host_impl_
->ScrollEnd();
1362 gfx::Vector2dF(5, 10),
1363 outer_scroll_layer
->CurrentScrollOffset());
1366 inner_scroll_layer
->CurrentScrollOffset());
1368 // Scroll by the outer viewport's max scroll extent, there the remainder
1369 // should bubble up to the inner viewport.
1370 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1371 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f
, 200.f
));
1372 host_impl_
->ScrollEnd();
1375 gfx::Vector2dF(100, 100),
1376 outer_scroll_layer
->CurrentScrollOffset());
1378 gfx::Vector2dF(5, 10),
1379 inner_scroll_layer
->CurrentScrollOffset());
1381 // Scroll by the inner viewport's max scroll extent, it should all go to the
1383 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1384 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f
, 80.f
));
1385 host_impl_
->ScrollEnd();
1388 gfx::Vector2dF(100, 100),
1389 outer_scroll_layer
->CurrentScrollOffset());
1391 gfx::Vector2dF(50, 50),
1392 inner_scroll_layer
->CurrentScrollOffset());
1395 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1396 ui::LatencyInfo latency_info
;
1397 latency_info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0,
1399 scoped_ptr
<SwapPromise
> swap_promise(
1400 new LatencyInfoSwapPromise(latency_info
));
1402 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1403 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1404 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1405 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1406 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1407 host_impl_
->ScrollEnd();
1409 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1410 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1411 EXPECT_EQ(latency_info
.trace_id(), scroll_info
->swap_promises
[0]->TraceId());
1414 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1415 // up to the scroll_parent, rather than the stacking parent.
1416 TEST_F(LayerTreeHostImplTest
, ScrollBubblesToScrollParent
) {
1417 LayerImpl
* viewport_scroll
=
1418 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1419 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1421 // Set up two scrolling children of the root, one of which is a scroll parent
1422 // to the other. Scrolls bubbling from the child should bubble to the parent,
1423 // not the viewport.
1426 LayerImpl
*child_clip
;
1428 scoped_ptr
<LayerImpl
> scroll_parent_clip
=
1429 LayerImpl::Create(host_impl_
->active_tree(), 6);
1430 scoped_ptr
<LayerImpl
> scroll_parent
= CreateScrollableLayer(
1431 7, gfx::Size(10, 10), scroll_parent_clip
.get());
1432 parent
= scroll_parent
.get();
1433 scroll_parent_clip
->AddChild(scroll_parent
.Pass());
1435 viewport_scroll
->AddChild(scroll_parent_clip
.Pass());
1437 scoped_ptr
<LayerImpl
> scroll_child_clip
=
1438 LayerImpl::Create(host_impl_
->active_tree(), 8);
1439 scoped_ptr
<LayerImpl
> scroll_child
= CreateScrollableLayer(
1440 9, gfx::Size(10, 10), scroll_child_clip
.get());
1441 child
= scroll_child
.get();
1442 scroll_child
->SetPosition(gfx::Point(20, 20));
1443 scroll_child_clip
->AddChild(scroll_child
.Pass());
1445 child_clip
= scroll_child_clip
.get();
1446 viewport_scroll
->AddChild(scroll_child_clip
.Pass());
1448 child_clip
->SetScrollParent(parent
);
1453 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1454 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1455 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1456 host_impl_
->ScrollEnd();
1458 // The child should be fully scrolled by the first ScrollBy.
1459 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child
->CurrentScrollOffset());
1461 // The scroll_parent should receive the bubbled up second ScrollBy.
1462 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent
->CurrentScrollOffset());
1464 // The viewport shouldn't have been scrolled at all.
1466 gfx::Vector2dF(0, 0),
1467 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1469 gfx::Vector2dF(0, 0),
1470 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1474 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1475 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1476 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1477 host_impl_
->ScrollEnd();
1479 // The first ScrollBy should scroll the parent to its extent.
1480 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent
->CurrentScrollOffset());
1482 // The viewport should now be next in bubbling order.
1484 gfx::Vector2dF(2, 1),
1485 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1487 gfx::Vector2dF(0, 0),
1488 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1493 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1494 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1495 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1498 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1499 DCHECK(scroll_layer
);
1501 float min_page_scale
= 1.f
;
1502 float max_page_scale
= 4.f
;
1504 // Basic pinch zoom in gesture
1506 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1508 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1510 float page_scale_delta
= 2.f
;
1511 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1512 host_impl_
->PinchGestureBegin();
1513 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1514 host_impl_
->PinchGestureEnd();
1515 host_impl_
->ScrollEnd();
1516 EXPECT_FALSE(did_request_animate_
);
1517 EXPECT_TRUE(did_request_redraw_
);
1518 EXPECT_TRUE(did_request_commit_
);
1520 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1521 host_impl_
->ProcessScrollDeltas();
1522 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1527 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1529 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1530 float page_scale_delta
= 10.f
;
1532 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1533 host_impl_
->PinchGestureBegin();
1534 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1535 host_impl_
->PinchGestureEnd();
1536 host_impl_
->ScrollEnd();
1538 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1539 host_impl_
->ProcessScrollDeltas();
1540 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1543 // Zoom-out clamping
1545 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1547 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1548 scroll_layer
->PullDeltaForMainThread();
1549 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1551 float page_scale_delta
= 0.1f
;
1552 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1553 host_impl_
->PinchGestureBegin();
1554 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1555 host_impl_
->PinchGestureEnd();
1556 host_impl_
->ScrollEnd();
1558 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1559 host_impl_
->ProcessScrollDeltas();
1560 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1562 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1565 // Two-finger panning should not happen based on pinch events only
1567 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1569 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1570 scroll_layer
->PullDeltaForMainThread();
1571 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1573 float page_scale_delta
= 1.f
;
1574 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1575 host_impl_
->PinchGestureBegin();
1576 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1577 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1578 host_impl_
->PinchGestureEnd();
1579 host_impl_
->ScrollEnd();
1581 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1582 host_impl_
->ProcessScrollDeltas();
1583 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1584 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1587 // Two-finger panning should work with interleaved scroll events
1589 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1591 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1592 scroll_layer
->PullDeltaForMainThread();
1593 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1595 float page_scale_delta
= 1.f
;
1596 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1597 host_impl_
->PinchGestureBegin();
1598 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1599 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1600 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1601 host_impl_
->PinchGestureEnd();
1602 host_impl_
->ScrollEnd();
1604 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1605 host_impl_
->ProcessScrollDeltas();
1606 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1607 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1608 gfx::Vector2d(-10, -10)));
1611 // Two-finger panning should work when starting fully zoomed out.
1613 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1614 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1615 scroll_layer
->PullDeltaForMainThread();
1616 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1618 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1619 host_impl_
->PinchGestureBegin();
1620 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1621 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1622 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1623 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1624 host_impl_
->PinchGestureEnd();
1625 host_impl_
->ScrollEnd();
1627 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1628 host_impl_
->ProcessScrollDeltas();
1629 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1630 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1631 gfx::Vector2d(20, 20)));
1635 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1636 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1637 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1640 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1641 DCHECK(scroll_layer
);
1643 float min_page_scale
= 0.5f
;
1644 float max_page_scale
= 4.f
;
1645 base::TimeTicks start_time
= base::TimeTicks() +
1646 base::TimeDelta::FromSeconds(1);
1647 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1648 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1649 base::TimeTicks end_time
= start_time
+ duration
;
1651 BeginFrameArgs begin_frame_args
=
1652 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1654 // Non-anchor zoom-in
1656 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1658 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1660 did_request_redraw_
= false;
1661 did_request_animate_
= false;
1662 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1663 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1668 host_impl_
->ActivateSyncTree();
1669 EXPECT_FALSE(did_request_redraw_
);
1670 EXPECT_TRUE(did_request_animate_
);
1672 did_request_redraw_
= false;
1673 did_request_animate_
= false;
1674 begin_frame_args
.frame_time
= start_time
;
1675 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1676 host_impl_
->Animate();
1677 EXPECT_TRUE(did_request_redraw_
);
1678 EXPECT_TRUE(did_request_animate_
);
1679 host_impl_
->DidFinishImplFrame();
1681 did_request_redraw_
= false;
1682 did_request_animate_
= false;
1683 begin_frame_args
.frame_time
= halfway_through_animation
;
1684 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1685 host_impl_
->Animate();
1686 EXPECT_TRUE(did_request_redraw_
);
1687 EXPECT_TRUE(did_request_animate_
);
1688 host_impl_
->DidFinishImplFrame();
1690 did_request_redraw_
= false;
1691 did_request_animate_
= false;
1692 did_request_commit_
= false;
1693 begin_frame_args
.frame_time
= end_time
;
1694 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1695 host_impl_
->Animate();
1696 EXPECT_TRUE(did_request_commit_
);
1697 EXPECT_FALSE(did_request_animate_
);
1698 host_impl_
->DidFinishImplFrame();
1700 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1701 host_impl_
->ProcessScrollDeltas();
1702 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1703 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1704 gfx::Vector2d(-50, -50)));
1707 start_time
+= base::TimeDelta::FromSeconds(10);
1708 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1709 end_time
+= base::TimeDelta::FromSeconds(10);
1713 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1715 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1717 did_request_redraw_
= false;
1718 did_request_animate_
= false;
1719 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1720 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1721 gfx::Vector2d(25, 25),
1725 host_impl_
->ActivateSyncTree();
1726 EXPECT_FALSE(did_request_redraw_
);
1727 EXPECT_TRUE(did_request_animate_
);
1729 did_request_redraw_
= false;
1730 did_request_animate_
= false;
1731 begin_frame_args
.frame_time
= start_time
;
1732 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1733 host_impl_
->Animate();
1734 EXPECT_TRUE(did_request_redraw_
);
1735 EXPECT_TRUE(did_request_animate_
);
1736 host_impl_
->DidFinishImplFrame();
1738 did_request_redraw_
= false;
1739 did_request_commit_
= false;
1740 did_request_animate_
= false;
1741 begin_frame_args
.frame_time
= end_time
;
1742 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1743 host_impl_
->Animate();
1744 EXPECT_TRUE(did_request_redraw_
);
1745 EXPECT_FALSE(did_request_animate_
);
1746 EXPECT_TRUE(did_request_commit_
);
1747 host_impl_
->DidFinishImplFrame();
1749 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1750 host_impl_
->ProcessScrollDeltas();
1751 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1752 // Pushed to (0,0) via clamping against contents layer size.
1753 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1754 gfx::Vector2d(-50, -50)));
1758 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1759 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1760 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1763 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1764 DCHECK(scroll_layer
);
1766 float min_page_scale
= 0.5f
;
1767 float max_page_scale
= 4.f
;
1768 base::TimeTicks start_time
= base::TimeTicks() +
1769 base::TimeDelta::FromSeconds(1);
1770 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1771 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1772 base::TimeTicks end_time
= start_time
+ duration
;
1774 BeginFrameArgs begin_frame_args
=
1775 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1777 // Anchor zoom with unchanged page scale should not change scroll or scale.
1779 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1781 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1783 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1784 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1789 host_impl_
->ActivateSyncTree();
1790 begin_frame_args
.frame_time
= start_time
;
1791 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1792 host_impl_
->Animate();
1793 host_impl_
->DidFinishImplFrame();
1795 begin_frame_args
.frame_time
= halfway_through_animation
;
1796 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1797 host_impl_
->Animate();
1798 EXPECT_TRUE(did_request_redraw_
);
1799 host_impl_
->DidFinishImplFrame();
1801 begin_frame_args
.frame_time
= end_time
;
1802 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1803 host_impl_
->Animate();
1804 EXPECT_TRUE(did_request_commit_
);
1805 host_impl_
->DidFinishImplFrame();
1807 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1808 host_impl_
->ProcessScrollDeltas();
1809 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1810 ExpectNone(*scroll_info
, scroll_layer
->id());
1814 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1815 host_impl_
->CreatePendingTree();
1816 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
1817 CreateScrollAndContentsLayers(
1818 host_impl_
->pending_tree(),
1819 gfx::Size(100, 100));
1820 host_impl_
->ActivateSyncTree();
1823 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1824 DCHECK(scroll_layer
);
1826 float min_page_scale
= 0.5f
;
1827 float max_page_scale
= 4.f
;
1828 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1830 host_impl_
->ActivateSyncTree();
1832 base::TimeTicks start_time
= base::TimeTicks() +
1833 base::TimeDelta::FromSeconds(1);
1834 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1835 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1836 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1837 base::TimeTicks end_time
= start_time
+ duration
;
1838 float target_scale
= 2.f
;
1840 BeginFrameArgs begin_frame_args
=
1841 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1843 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1845 // Make sure TakePageScaleAnimation works properly.
1847 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1848 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1853 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1854 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1855 EXPECT_EQ(target_scale
, psa
->scale
);
1856 EXPECT_EQ(duration
, psa
->duration
);
1857 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1859 // Recreate the PSA. Nothing should happen here since the tree containing the
1860 // PSA hasn't been activated yet.
1861 did_request_redraw_
= false;
1862 did_request_animate_
= false;
1863 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1864 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1869 begin_frame_args
.frame_time
= halfway_through_animation
;
1870 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1871 host_impl_
->Animate();
1872 EXPECT_FALSE(did_request_animate_
);
1873 EXPECT_FALSE(did_request_redraw_
);
1874 host_impl_
->DidFinishImplFrame();
1876 // Activate the sync tree. This should cause the animation to become enabled.
1877 // It should also clear the pointer on the sync tree.
1878 host_impl_
->ActivateSyncTree();
1880 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1881 EXPECT_FALSE(did_request_redraw_
);
1882 EXPECT_TRUE(did_request_animate_
);
1884 start_time
+= base::TimeDelta::FromSeconds(10);
1885 third_through_animation
+= base::TimeDelta::FromSeconds(10);
1886 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1887 end_time
+= base::TimeDelta::FromSeconds(10);
1889 // From here on, make sure the animation runs as normal.
1890 did_request_redraw_
= false;
1891 did_request_animate_
= false;
1892 begin_frame_args
.frame_time
= start_time
;
1893 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1894 host_impl_
->Animate();
1895 EXPECT_TRUE(did_request_redraw_
);
1896 EXPECT_TRUE(did_request_animate_
);
1897 host_impl_
->DidFinishImplFrame();
1899 did_request_redraw_
= false;
1900 did_request_animate_
= false;
1901 begin_frame_args
.frame_time
= third_through_animation
;
1902 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1903 host_impl_
->Animate();
1904 EXPECT_TRUE(did_request_redraw_
);
1905 EXPECT_TRUE(did_request_animate_
);
1906 host_impl_
->DidFinishImplFrame();
1908 // Another activation shouldn't have any effect on the animation.
1909 host_impl_
->ActivateSyncTree();
1911 did_request_redraw_
= false;
1912 did_request_animate_
= false;
1913 begin_frame_args
.frame_time
= halfway_through_animation
;
1914 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1915 host_impl_
->Animate();
1916 EXPECT_TRUE(did_request_redraw_
);
1917 EXPECT_TRUE(did_request_animate_
);
1918 host_impl_
->DidFinishImplFrame();
1920 did_request_redraw_
= false;
1921 did_request_animate_
= false;
1922 did_request_commit_
= false;
1923 begin_frame_args
.frame_time
= end_time
;
1924 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1925 host_impl_
->Animate();
1926 EXPECT_TRUE(did_request_commit_
);
1927 EXPECT_FALSE(did_request_animate_
);
1928 host_impl_
->DidFinishImplFrame();
1930 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1931 host_impl_
->ProcessScrollDeltas();
1932 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
1933 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1934 gfx::Vector2d(-50, -50)));
1937 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
1938 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1939 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1942 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1943 DCHECK(scroll_layer
);
1945 base::TimeTicks start_time
=
1946 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1947 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1948 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1949 base::TimeTicks end_time
= start_time
+ duration
;
1951 BeginFrameArgs begin_frame_args
=
1952 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1954 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1955 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1957 did_complete_page_scale_animation_
= false;
1958 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1959 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1960 gfx::Vector2d(), false, 2.f
, duration
)));
1961 host_impl_
->ActivateSyncTree();
1962 begin_frame_args
.frame_time
= start_time
;
1963 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1964 host_impl_
->Animate();
1965 EXPECT_FALSE(did_complete_page_scale_animation_
);
1966 host_impl_
->DidFinishImplFrame();
1968 begin_frame_args
.frame_time
= halfway_through_animation
;
1969 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1970 host_impl_
->Animate();
1971 EXPECT_FALSE(did_complete_page_scale_animation_
);
1972 host_impl_
->DidFinishImplFrame();
1974 begin_frame_args
.frame_time
= end_time
;
1975 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1976 host_impl_
->Animate();
1977 EXPECT_TRUE(did_complete_page_scale_animation_
);
1978 host_impl_
->DidFinishImplFrame();
1981 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
1983 LayerTreeHostImplOverridePhysicalTime(
1984 const LayerTreeSettings
& settings
,
1985 LayerTreeHostImplClient
* client
,
1987 SharedBitmapManager
* manager
,
1988 TaskGraphRunner
* task_graph_runner
,
1989 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
1990 : LayerTreeHostImpl(settings
,
1993 rendering_stats_instrumentation
,
1999 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
2000 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
2001 fake_current_physical_time_
);
2004 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
2005 fake_current_physical_time_
= fake_now
;
2009 base::TimeTicks fake_current_physical_time_
;
2012 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
2014 void SetupLayers(LayerTreeSettings settings
) {
2015 gfx::Size
content_size(100, 100);
2017 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
2018 new LayerTreeHostImplOverridePhysicalTime(
2019 settings
, this, &proxy_
, &shared_bitmap_manager_
,
2020 &task_graph_runner_
, &stats_instrumentation_
);
2021 host_impl_
= make_scoped_ptr(host_impl_override_time
);
2022 host_impl_
->InitializeRenderer(CreateOutputSurface());
2024 SetupScrollAndContentsLayers(content_size
);
2025 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2026 host_impl_
->SetViewportSize(
2027 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
2029 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
2030 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 400,
2031 VERTICAL
, 10, 0, false, true);
2032 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
2034 LayerImpl
* scroll
= host_impl_
->InnerViewportScrollLayer();
2035 LayerImpl
* root
= scroll
->parent()->parent();
2036 scrollbar
->SetScrollLayerAndClipLayerByIds(scroll
->id(), root
->id());
2037 root
->AddChild(scrollbar
.Pass());
2039 host_impl_
->active_tree()->DidBecomeActive();
2043 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
2044 LayerTreeSettings settings
;
2045 settings
.scrollbar_animator
= animator
;
2046 settings
.scrollbar_fade_delay_ms
= 20;
2047 settings
.scrollbar_fade_duration_ms
= 20;
2049 SetupLayers(settings
);
2051 base::TimeTicks fake_now
= base::TimeTicks::Now();
2053 EXPECT_FALSE(did_request_animate_
);
2054 EXPECT_FALSE(did_request_redraw_
);
2055 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2056 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2058 // If no scroll happened during a scroll gesture, it should have no effect.
2059 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2060 host_impl_
->ScrollEnd();
2061 EXPECT_FALSE(did_request_animate_
);
2062 EXPECT_FALSE(did_request_redraw_
);
2063 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2064 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2066 // After a scroll, a scrollbar animation should be scheduled about 20ms from
2068 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2069 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2070 EXPECT_FALSE(did_request_animate_
);
2071 EXPECT_TRUE(did_request_redraw_
);
2072 did_request_redraw_
= false;
2073 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2074 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2076 host_impl_
->ScrollEnd();
2077 EXPECT_FALSE(did_request_animate_
);
2078 EXPECT_FALSE(did_request_redraw_
);
2079 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2080 requested_animation_delay_
);
2081 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2083 fake_now
+= requested_animation_delay_
;
2084 requested_animation_delay_
= base::TimeDelta();
2085 animation_task_
.Run();
2086 animation_task_
= base::Closure();
2087 EXPECT_TRUE(did_request_animate_
);
2088 did_request_animate_
= false;
2089 EXPECT_FALSE(did_request_redraw_
);
2091 // After the scrollbar animation begins, we should start getting redraws.
2092 BeginFrameArgs begin_frame_args
=
2093 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, fake_now
);
2094 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2095 host_impl_
->Animate();
2096 EXPECT_TRUE(did_request_animate_
);
2097 did_request_animate_
= false;
2098 EXPECT_TRUE(did_request_redraw_
);
2099 did_request_redraw_
= false;
2100 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2101 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2102 host_impl_
->DidFinishImplFrame();
2104 // Setting the scroll offset outside a scroll should also cause the
2105 // scrollbar to appear and to schedule a scrollbar animation.
2106 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2107 gfx::ScrollOffset(5, 5));
2108 EXPECT_FALSE(did_request_animate_
);
2109 EXPECT_FALSE(did_request_redraw_
);
2110 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2111 requested_animation_delay_
);
2112 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2113 requested_animation_delay_
= base::TimeDelta();
2114 animation_task_
= base::Closure();
2116 // Scrollbar animation is not triggered unnecessarily.
2117 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2118 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2119 EXPECT_FALSE(did_request_animate_
);
2120 EXPECT_TRUE(did_request_redraw_
);
2121 did_request_redraw_
= false;
2122 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2123 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2125 host_impl_
->ScrollEnd();
2126 EXPECT_FALSE(did_request_animate_
);
2127 EXPECT_FALSE(did_request_redraw_
);
2128 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2129 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2131 // Changing page scale triggers scrollbar animation.
2132 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2133 host_impl_
->SetPageScaleOnActiveTree(1.1f
);
2134 EXPECT_FALSE(did_request_animate_
);
2135 EXPECT_FALSE(did_request_redraw_
);
2136 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2137 requested_animation_delay_
);
2138 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2139 requested_animation_delay_
= base::TimeDelta();
2140 animation_task_
= base::Closure();
2144 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
2145 RunTest(LayerTreeSettings::LINEAR_FADE
);
2148 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
2149 RunTest(LayerTreeSettings::THINNING
);
2152 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2153 float device_scale_factor
) {
2154 LayerTreeSettings settings
;
2155 settings
.scrollbar_fade_delay_ms
= 500;
2156 settings
.scrollbar_fade_duration_ms
= 300;
2157 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
2159 gfx::Size
viewport_size(300, 200);
2160 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
2161 gfx::ScaleSize(viewport_size
, device_scale_factor
));
2162 gfx::Size
content_size(1000, 1000);
2164 CreateHostImpl(settings
, CreateOutputSurface());
2165 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
2166 host_impl_
->SetViewportSize(device_viewport_size
);
2168 scoped_ptr
<LayerImpl
> root
=
2169 LayerImpl::Create(host_impl_
->active_tree(), 1);
2170 root
->SetBounds(viewport_size
);
2171 root
->SetHasRenderSurface(true);
2173 scoped_ptr
<LayerImpl
> scroll
=
2174 LayerImpl::Create(host_impl_
->active_tree(), 2);
2175 scroll
->SetScrollClipLayer(root
->id());
2176 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2177 scroll
->SetBounds(content_size
);
2178 scroll
->SetIsContainerForFixedPositionLayers(true);
2180 scoped_ptr
<LayerImpl
> contents
=
2181 LayerImpl::Create(host_impl_
->active_tree(), 3);
2182 contents
->SetDrawsContent(true);
2183 contents
->SetBounds(content_size
);
2185 // The scrollbar is on the right side.
2186 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
2187 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
2188 scrollbar
->SetDrawsContent(true);
2189 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
2190 scrollbar
->SetPosition(gfx::Point(285, 0));
2192 scroll
->AddChild(contents
.Pass());
2193 root
->AddChild(scroll
.Pass());
2194 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
2195 root
->AddChild(scrollbar
.Pass());
2197 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2198 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
2200 host_impl_
->active_tree()->DidBecomeActive();
2203 LayerImpl
* root_scroll
=
2204 host_impl_
->active_tree()->InnerViewportScrollLayer();
2205 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
2206 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
2207 static_cast<ScrollbarAnimationControllerThinning
*>(
2208 root_scroll
->scrollbar_animation_controller());
2209 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
2211 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
2212 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2214 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
2215 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2217 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2218 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2220 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
2221 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2222 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2224 did_request_redraw_
= false;
2225 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2226 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
2227 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2228 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
2229 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2230 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
2231 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2234 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
2235 SetupMouseMoveAtWithDeviceScale(1.f
);
2238 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
2239 SetupMouseMoveAtWithDeviceScale(2.f
);
2242 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
2243 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2244 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2245 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2248 CompositorFrameMetadata metadata
=
2249 host_impl_
->MakeCompositorFrameMetadata();
2250 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
2251 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
2252 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
2253 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2254 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2255 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2256 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2257 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2260 // Scrolling should update metadata immediately.
2261 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2262 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2263 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2265 CompositorFrameMetadata metadata
=
2266 host_impl_
->MakeCompositorFrameMetadata();
2267 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2269 host_impl_
->ScrollEnd();
2271 CompositorFrameMetadata metadata
=
2272 host_impl_
->MakeCompositorFrameMetadata();
2273 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2276 // Root "overflow: hidden" properties should be reflected on the outer
2277 // viewport scroll layer.
2279 host_impl_
->active_tree()
2280 ->OuterViewportScrollLayer()
2281 ->set_user_scrollable_horizontal(false);
2282 CompositorFrameMetadata metadata
=
2283 host_impl_
->MakeCompositorFrameMetadata();
2284 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2285 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2287 host_impl_
->active_tree()
2288 ->OuterViewportScrollLayer()
2289 ->set_user_scrollable_vertical(false);
2290 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2291 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2292 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2295 // Re-enable scrollability and verify that overflows are no longer hidden.
2297 host_impl_
->active_tree()
2298 ->OuterViewportScrollLayer()
2299 ->set_user_scrollable_horizontal(true);
2300 host_impl_
->active_tree()
2301 ->OuterViewportScrollLayer()
2302 ->set_user_scrollable_vertical(true);
2303 CompositorFrameMetadata metadata
=
2304 host_impl_
->MakeCompositorFrameMetadata();
2305 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2306 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2309 // Root "overflow: hidden" properties should also be reflected on the
2310 // inner viewport scroll layer.
2312 host_impl_
->active_tree()
2313 ->InnerViewportScrollLayer()
2314 ->set_user_scrollable_horizontal(false);
2315 CompositorFrameMetadata metadata
=
2316 host_impl_
->MakeCompositorFrameMetadata();
2317 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2318 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2320 host_impl_
->active_tree()
2321 ->InnerViewportScrollLayer()
2322 ->set_user_scrollable_vertical(false);
2323 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2324 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2325 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2328 // Page scale should update metadata correctly (shrinking only the viewport).
2329 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
2330 host_impl_
->PinchGestureBegin();
2331 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
2332 host_impl_
->PinchGestureEnd();
2333 host_impl_
->ScrollEnd();
2335 CompositorFrameMetadata metadata
=
2336 host_impl_
->MakeCompositorFrameMetadata();
2337 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2338 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
2339 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
2340 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2341 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2342 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2345 // Likewise if set from the main thread.
2346 host_impl_
->ProcessScrollDeltas();
2347 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
2348 host_impl_
->SetPageScaleOnActiveTree(4.f
);
2350 CompositorFrameMetadata metadata
=
2351 host_impl_
->MakeCompositorFrameMetadata();
2352 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2353 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
2354 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
2355 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2356 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2357 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2361 class DidDrawCheckLayer
: public LayerImpl
{
2363 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2364 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2367 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2368 will_draw_called_
= true;
2369 if (will_draw_returns_false_
)
2371 return LayerImpl::WillDraw(draw_mode
, provider
);
2374 void AppendQuads(RenderPass
* render_pass
,
2375 AppendQuadsData
* append_quads_data
) override
{
2376 append_quads_called_
= true;
2377 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2380 void DidDraw(ResourceProvider
* provider
) override
{
2381 did_draw_called_
= true;
2382 LayerImpl::DidDraw(provider
);
2385 bool will_draw_called() const { return will_draw_called_
; }
2386 bool append_quads_called() const { return append_quads_called_
; }
2387 bool did_draw_called() const { return did_draw_called_
; }
2389 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2391 void ClearDidDrawCheck() {
2392 will_draw_called_
= false;
2393 append_quads_called_
= false;
2394 did_draw_called_
= false;
2397 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2399 void AddCopyRequest() {
2400 ScopedPtrVector
<CopyOutputRequest
> requests
;
2402 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2403 SetHasRenderSurface(true);
2404 PassCopyRequests(&requests
);
2408 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2409 : LayerImpl(tree_impl
, id
),
2410 will_draw_returns_false_(false),
2411 will_draw_called_(false),
2412 append_quads_called_(false),
2413 did_draw_called_(false) {
2414 SetBounds(gfx::Size(10, 10));
2415 SetDrawsContent(true);
2416 draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
2420 bool will_draw_returns_false_
;
2421 bool will_draw_called_
;
2422 bool append_quads_called_
;
2423 bool did_draw_called_
;
2426 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2427 // The root layer is always drawn, so run this test on a child layer that
2428 // will be masked out by the root layer's bounds.
2429 host_impl_
->active_tree()->SetRootLayer(
2430 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2431 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2432 host_impl_
->active_tree()->root_layer());
2434 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2435 root
->SetHasRenderSurface(true);
2436 DidDrawCheckLayer
* layer
=
2437 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2440 LayerTreeHostImpl::FrameData frame
;
2441 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2442 host_impl_
->DrawLayers(&frame
);
2443 host_impl_
->DidDrawAllLayers(frame
);
2445 EXPECT_TRUE(layer
->will_draw_called());
2446 EXPECT_TRUE(layer
->append_quads_called());
2447 EXPECT_TRUE(layer
->did_draw_called());
2450 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2453 LayerTreeHostImpl::FrameData frame
;
2455 layer
->set_will_draw_returns_false();
2456 layer
->ClearDidDrawCheck();
2458 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2459 host_impl_
->DrawLayers(&frame
);
2460 host_impl_
->DidDrawAllLayers(frame
);
2462 EXPECT_TRUE(layer
->will_draw_called());
2463 EXPECT_FALSE(layer
->append_quads_called());
2464 EXPECT_FALSE(layer
->did_draw_called());
2468 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2469 // The root layer is always drawn, so run this test on a child layer that
2470 // will be masked out by the root layer's bounds.
2471 host_impl_
->active_tree()->SetRootLayer(
2472 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2473 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2474 host_impl_
->active_tree()->root_layer());
2475 root
->SetMasksToBounds(true);
2476 root
->SetHasRenderSurface(true);
2477 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2478 DidDrawCheckLayer
* layer
=
2479 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2480 // Ensure visible_layer_rect for layer is empty.
2481 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2482 layer
->SetBounds(gfx::Size(10, 10));
2484 LayerTreeHostImpl::FrameData frame
;
2486 EXPECT_FALSE(layer
->will_draw_called());
2487 EXPECT_FALSE(layer
->did_draw_called());
2489 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
2490 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2491 host_impl_
->DrawLayers(&frame
);
2492 host_impl_
->DidDrawAllLayers(frame
);
2494 EXPECT_FALSE(layer
->will_draw_called());
2495 EXPECT_FALSE(layer
->did_draw_called());
2497 EXPECT_TRUE(layer
->visible_layer_rect().IsEmpty());
2499 // Ensure visible_layer_rect for layer is not empty
2500 layer
->SetPosition(gfx::PointF());
2502 EXPECT_FALSE(layer
->will_draw_called());
2503 EXPECT_FALSE(layer
->did_draw_called());
2505 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2506 host_impl_
->DrawLayers(&frame
);
2507 host_impl_
->DidDrawAllLayers(frame
);
2509 EXPECT_TRUE(layer
->will_draw_called());
2510 EXPECT_TRUE(layer
->did_draw_called());
2512 EXPECT_FALSE(layer
->visible_layer_rect().IsEmpty());
2515 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2516 gfx::Size
big_size(1000, 1000);
2517 host_impl_
->SetViewportSize(big_size
);
2519 host_impl_
->active_tree()->SetRootLayer(
2520 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2521 DidDrawCheckLayer
* root
=
2522 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2524 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2525 DidDrawCheckLayer
* occluded_layer
=
2526 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2528 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2529 root
->SetHasRenderSurface(true);
2530 DidDrawCheckLayer
* top_layer
=
2531 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2532 // This layer covers the occluded_layer above. Make this layer large so it can
2534 top_layer
->SetBounds(big_size
);
2535 top_layer
->SetContentsOpaque(true);
2537 LayerTreeHostImpl::FrameData frame
;
2539 EXPECT_FALSE(occluded_layer
->will_draw_called());
2540 EXPECT_FALSE(occluded_layer
->did_draw_called());
2541 EXPECT_FALSE(top_layer
->will_draw_called());
2542 EXPECT_FALSE(top_layer
->did_draw_called());
2544 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2545 host_impl_
->DrawLayers(&frame
);
2546 host_impl_
->DidDrawAllLayers(frame
);
2548 EXPECT_FALSE(occluded_layer
->will_draw_called());
2549 EXPECT_FALSE(occluded_layer
->did_draw_called());
2550 EXPECT_TRUE(top_layer
->will_draw_called());
2551 EXPECT_TRUE(top_layer
->did_draw_called());
2554 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2555 host_impl_
->active_tree()->SetRootLayer(
2556 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2557 DidDrawCheckLayer
* root
=
2558 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2560 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2561 root
->SetHasRenderSurface(true);
2562 DidDrawCheckLayer
* layer1
=
2563 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2565 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2566 DidDrawCheckLayer
* layer2
=
2567 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2569 layer1
->SetHasRenderSurface(true);
2570 layer1
->SetShouldFlattenTransform(true);
2572 EXPECT_FALSE(root
->did_draw_called());
2573 EXPECT_FALSE(layer1
->did_draw_called());
2574 EXPECT_FALSE(layer2
->did_draw_called());
2576 LayerTreeHostImpl::FrameData frame
;
2577 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2578 host_impl_
->active_tree()->root_layer());
2579 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2580 host_impl_
->DrawLayers(&frame
);
2581 host_impl_
->DidDrawAllLayers(frame
);
2583 EXPECT_TRUE(root
->did_draw_called());
2584 EXPECT_TRUE(layer1
->did_draw_called());
2585 EXPECT_TRUE(layer2
->did_draw_called());
2587 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2588 EXPECT_TRUE(layer1
->render_surface());
2591 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2593 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2596 bool had_incomplete_tile
,
2598 ResourceProvider
* resource_provider
) {
2599 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2602 had_incomplete_tile
,
2604 resource_provider
));
2607 void AppendQuads(RenderPass
* render_pass
,
2608 AppendQuadsData
* append_quads_data
) override
{
2609 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2610 if (had_incomplete_tile_
)
2611 append_quads_data
->num_incomplete_tiles
++;
2613 append_quads_data
->num_missing_tiles
++;
2617 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2620 bool had_incomplete_tile
,
2622 ResourceProvider
* resource_provider
)
2623 : DidDrawCheckLayer(tree_impl
, id
),
2624 tile_missing_(tile_missing
),
2625 had_incomplete_tile_(had_incomplete_tile
) {
2627 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2631 bool had_incomplete_tile_
;
2634 struct PrepareToDrawSuccessTestCase
{
2636 bool has_missing_tile
= false;
2637 bool has_incomplete_tile
= false;
2638 bool is_animating
= false;
2639 bool has_copy_request
= false;
2641 bool high_res_required
= false;
2643 State layer_between
;
2645 DrawResult expected_result
;
2647 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2648 : expected_result(result
) {}
2651 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2652 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2655 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2656 // 1. Animated layer first.
2657 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2658 cases
.back().layer_before
.is_animating
= true;
2659 // 2. Animated layer between.
2660 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2661 cases
.back().layer_between
.is_animating
= true;
2662 // 3. Animated layer last.
2663 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2664 cases
.back().layer_after
.is_animating
= true;
2665 // 4. Missing tile first.
2666 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2667 cases
.back().layer_before
.has_missing_tile
= true;
2668 // 5. Missing tile between.
2669 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2670 cases
.back().layer_between
.has_missing_tile
= true;
2671 // 6. Missing tile last.
2672 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2673 cases
.back().layer_after
.has_missing_tile
= true;
2674 // 7. Incomplete tile first.
2675 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2676 cases
.back().layer_before
.has_incomplete_tile
= true;
2677 // 8. Incomplete tile between.
2678 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2679 cases
.back().layer_between
.has_incomplete_tile
= true;
2680 // 9. Incomplete tile last.
2681 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2682 cases
.back().layer_after
.has_incomplete_tile
= true;
2683 // 10. Animation with missing tile.
2685 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2686 cases
.back().layer_between
.has_missing_tile
= true;
2687 cases
.back().layer_between
.is_animating
= true;
2688 // 11. Animation with incomplete tile.
2689 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2690 cases
.back().layer_between
.has_incomplete_tile
= true;
2691 cases
.back().layer_between
.is_animating
= true;
2693 // 12. High res required.
2694 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2695 cases
.back().high_res_required
= true;
2696 // 13. High res required with incomplete tile.
2698 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2699 cases
.back().high_res_required
= true;
2700 cases
.back().layer_between
.has_incomplete_tile
= true;
2701 // 14. High res required with missing tile.
2703 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2704 cases
.back().high_res_required
= true;
2705 cases
.back().layer_between
.has_missing_tile
= true;
2707 // 15. High res required is higher priority than animating missing tiles.
2709 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2710 cases
.back().high_res_required
= true;
2711 cases
.back().layer_between
.has_missing_tile
= true;
2712 cases
.back().layer_after
.has_missing_tile
= true;
2713 cases
.back().layer_after
.is_animating
= true;
2714 // 16. High res required is higher priority than animating missing tiles.
2716 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2717 cases
.back().high_res_required
= true;
2718 cases
.back().layer_between
.has_missing_tile
= true;
2719 cases
.back().layer_before
.has_missing_tile
= true;
2720 cases
.back().layer_before
.is_animating
= true;
2722 host_impl_
->active_tree()->SetRootLayer(
2723 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2724 DidDrawCheckLayer
* root
=
2725 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2726 root
->SetHasRenderSurface(true);
2728 LayerTreeHostImpl::FrameData frame
;
2729 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2730 host_impl_
->DrawLayers(&frame
);
2731 host_impl_
->DidDrawAllLayers(frame
);
2732 host_impl_
->SwapBuffers(frame
);
2734 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2735 const auto& testcase
= cases
[i
];
2736 std::vector
<LayerImpl
*> to_remove
;
2737 for (auto* child
: root
->children())
2738 to_remove
.push_back(child
);
2739 for (auto* child
: to_remove
)
2740 root
->RemoveChild(child
);
2742 std::ostringstream scope
;
2743 scope
<< "Test case: " << i
;
2744 SCOPED_TRACE(scope
.str());
2746 root
->AddChild(MissingTextureAnimatingLayer::Create(
2747 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2748 testcase
.layer_before
.has_incomplete_tile
,
2749 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2750 DidDrawCheckLayer
* before
=
2751 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2752 if (testcase
.layer_before
.has_copy_request
)
2753 before
->AddCopyRequest();
2755 root
->AddChild(MissingTextureAnimatingLayer::Create(
2756 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2757 testcase
.layer_between
.has_incomplete_tile
,
2758 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2759 DidDrawCheckLayer
* between
=
2760 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2761 if (testcase
.layer_between
.has_copy_request
)
2762 between
->AddCopyRequest();
2764 root
->AddChild(MissingTextureAnimatingLayer::Create(
2765 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2766 testcase
.layer_after
.has_incomplete_tile
,
2767 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2768 DidDrawCheckLayer
* after
=
2769 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2770 if (testcase
.layer_after
.has_copy_request
)
2771 after
->AddCopyRequest();
2773 if (testcase
.high_res_required
)
2774 host_impl_
->SetRequiresHighResToDraw();
2776 LayerTreeHostImpl::FrameData frame
;
2777 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2778 host_impl_
->DrawLayers(&frame
);
2779 host_impl_
->DidDrawAllLayers(frame
);
2780 host_impl_
->SwapBuffers(frame
);
2784 TEST_F(LayerTreeHostImplTest
,
2785 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2786 CreateHostImpl(DefaultSettings(),
2787 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2788 EXPECT_TRUE(host_impl_
->output_surface()
2790 .draw_and_swap_full_viewport_every_frame
);
2792 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2795 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2796 // 1. Animation with missing tile.
2797 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2798 cases
.back().layer_between
.has_missing_tile
= true;
2799 cases
.back().layer_between
.is_animating
= true;
2800 // 2. High res required with incomplete tile.
2801 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2802 cases
.back().high_res_required
= true;
2803 cases
.back().layer_between
.has_incomplete_tile
= true;
2804 // 3. High res required with missing tile.
2805 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2806 cases
.back().high_res_required
= true;
2807 cases
.back().layer_between
.has_missing_tile
= true;
2809 host_impl_
->active_tree()->SetRootLayer(
2810 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2811 DidDrawCheckLayer
* root
=
2812 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2813 root
->SetHasRenderSurface(true);
2815 LayerTreeHostImpl::FrameData frame
;
2816 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2817 host_impl_
->DrawLayers(&frame
);
2818 host_impl_
->DidDrawAllLayers(frame
);
2819 host_impl_
->SwapBuffers(frame
);
2821 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2822 const auto& testcase
= cases
[i
];
2823 std::vector
<LayerImpl
*> to_remove
;
2824 for (auto* child
: root
->children())
2825 to_remove
.push_back(child
);
2826 for (auto* child
: to_remove
)
2827 root
->RemoveChild(child
);
2829 std::ostringstream scope
;
2830 scope
<< "Test case: " << i
;
2831 SCOPED_TRACE(scope
.str());
2833 root
->AddChild(MissingTextureAnimatingLayer::Create(
2834 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2835 testcase
.layer_before
.has_incomplete_tile
,
2836 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2837 DidDrawCheckLayer
* before
=
2838 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2839 if (testcase
.layer_before
.has_copy_request
)
2840 before
->AddCopyRequest();
2842 root
->AddChild(MissingTextureAnimatingLayer::Create(
2843 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2844 testcase
.layer_between
.has_incomplete_tile
,
2845 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2846 DidDrawCheckLayer
* between
=
2847 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2848 if (testcase
.layer_between
.has_copy_request
)
2849 between
->AddCopyRequest();
2851 root
->AddChild(MissingTextureAnimatingLayer::Create(
2852 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2853 testcase
.layer_after
.has_incomplete_tile
,
2854 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2855 DidDrawCheckLayer
* after
=
2856 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2857 if (testcase
.layer_after
.has_copy_request
)
2858 after
->AddCopyRequest();
2860 if (testcase
.high_res_required
)
2861 host_impl_
->SetRequiresHighResToDraw();
2863 LayerTreeHostImpl::FrameData frame
;
2864 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2865 host_impl_
->DrawLayers(&frame
);
2866 host_impl_
->DidDrawAllLayers(frame
);
2867 host_impl_
->SwapBuffers(frame
);
2871 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2872 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2873 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2874 root
->SetHasRenderSurface(true);
2875 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2878 // Scroll event is ignored because layer is not scrollable.
2879 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2880 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2881 EXPECT_FALSE(did_request_redraw_
);
2882 EXPECT_FALSE(did_request_commit_
);
2885 TEST_F(LayerTreeHostImplTest
, ClampingAfterActivation
) {
2886 host_impl_
->CreatePendingTree();
2887 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2888 CreateScrollAndContentsLayers(host_impl_
->pending_tree(),
2889 gfx::Size(100, 100));
2890 host_impl_
->ActivateSyncTree();
2892 host_impl_
->CreatePendingTree();
2893 const gfx::ScrollOffset pending_scroll
= gfx::ScrollOffset(-100, -100);
2894 LayerImpl
* active_outer_layer
=
2895 host_impl_
->active_tree()->OuterViewportScrollLayer();
2896 LayerImpl
* pending_outer_layer
=
2897 host_impl_
->pending_tree()->OuterViewportScrollLayer();
2898 pending_outer_layer
->PushScrollOffsetFromMainThread(pending_scroll
);
2900 host_impl_
->ActivateSyncTree();
2901 // Scrolloffsets on the active tree will be clamped after activation.
2902 EXPECT_EQ(active_outer_layer
->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
2905 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
2907 LayerTreeHostImplTopControlsTest()
2908 // Make the clip size the same as the layer (content) size so the layer is
2910 : layer_size_(10, 10),
2911 clip_size_(layer_size_
),
2912 top_controls_height_(50) {
2913 viewport_size_
= gfx::Size(clip_size_
.width(),
2914 clip_size_
.height() + top_controls_height_
);
2917 bool CreateHostImpl(const LayerTreeSettings
& settings
,
2918 scoped_ptr
<OutputSurface
> output_surface
) override
{
2920 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
2922 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
2923 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2924 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2929 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2930 const gfx::Size
& inner_viewport_size
,
2931 const gfx::Size
& outer_viewport_size
,
2932 const gfx::Size
& scroll_layer_size
) {
2933 CreateHostImpl(settings_
, CreateOutputSurface());
2934 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2935 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2936 host_impl_
->DidChangeTopControlsPosition();
2938 scoped_ptr
<LayerImpl
> root
=
2939 LayerImpl::Create(host_impl_
->active_tree(), 1);
2940 scoped_ptr
<LayerImpl
> root_clip
=
2941 LayerImpl::Create(host_impl_
->active_tree(), 2);
2942 scoped_ptr
<LayerImpl
> page_scale
=
2943 LayerImpl::Create(host_impl_
->active_tree(), 3);
2945 scoped_ptr
<LayerImpl
> outer_scroll
=
2946 LayerImpl::Create(host_impl_
->active_tree(), 4);
2947 scoped_ptr
<LayerImpl
> outer_clip
=
2948 LayerImpl::Create(host_impl_
->active_tree(), 5);
2950 root_clip
->SetBounds(inner_viewport_size
);
2951 root
->SetScrollClipLayer(root_clip
->id());
2952 root
->SetBounds(outer_viewport_size
);
2953 root
->SetPosition(gfx::PointF());
2954 root
->SetDrawsContent(false);
2955 root
->SetIsContainerForFixedPositionLayers(true);
2956 root_clip
->SetHasRenderSurface(true);
2957 outer_clip
->SetBounds(outer_viewport_size
);
2958 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
2959 outer_scroll
->SetBounds(scroll_layer_size
);
2960 outer_scroll
->SetPosition(gfx::PointF());
2961 outer_scroll
->SetDrawsContent(false);
2962 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
2964 int inner_viewport_scroll_layer_id
= root
->id();
2965 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
2966 int page_scale_layer_id
= page_scale
->id();
2968 outer_clip
->AddChild(outer_scroll
.Pass());
2969 root
->AddChild(outer_clip
.Pass());
2970 page_scale
->AddChild(root
.Pass());
2971 root_clip
->AddChild(page_scale
.Pass());
2973 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2974 host_impl_
->active_tree()->SetViewportLayersFromIds(
2975 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2976 outer_viewport_scroll_layer_id
);
2978 host_impl_
->SetViewportSize(inner_viewport_size
);
2979 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2980 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
2984 gfx::Size layer_size_
;
2985 gfx::Size clip_size_
;
2986 gfx::Size viewport_size_
;
2987 float top_controls_height_
;
2989 LayerTreeSettings settings_
;
2990 }; // class LayerTreeHostImplTopControlsTest
2992 // Tests that, on a page with content the same size as the viewport, hiding
2993 // the top controls also increases the ScrollableSize (i.e. the content size).
2994 // Since the viewport got larger, the effective scrollable "content" also did.
2995 // This ensures, for one thing, that the overscroll glow is shown in the right
2997 TEST_F(LayerTreeHostImplTopControlsTest
,
2998 HidingTopControlsExpandsScrollableSize
) {
2999 SetupTopControlsAndScrollLayerWithVirtualViewport(
3000 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
3002 LayerTreeImpl
* active_tree
= host_impl_
->active_tree();
3004 // Create a content layer beneath the outer viewport scroll layer.
3005 int id
= host_impl_
->OuterViewportScrollLayer()->id();
3006 host_impl_
->OuterViewportScrollLayer()->AddChild(
3007 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2));
3008 LayerImpl
* content
= active_tree
->OuterViewportScrollLayer()->children()[0];
3009 content
->SetBounds(gfx::Size(50, 50));
3013 LayerImpl
* inner_container
= active_tree
->InnerViewportContainerLayer();
3014 LayerImpl
* outer_container
= active_tree
->OuterViewportContainerLayer();
3016 // The top controls should start off showing so the viewport should be shrunk.
3017 ASSERT_EQ(gfx::Size(50, 50), inner_container
->bounds());
3018 ASSERT_EQ(gfx::Size(50, 50), outer_container
->bounds());
3020 EXPECT_EQ(gfx::SizeF(50, 50), active_tree
->ScrollableSize());
3022 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3023 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3025 host_impl_
->top_controls_manager()->ScrollBegin();
3027 // Hide the top controls by a bit, the scrollable size should increase but the
3028 // actual content bounds shouldn't.
3030 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3031 ASSERT_EQ(gfx::Size(50, 75), inner_container
->bounds());
3032 ASSERT_EQ(gfx::Size(50, 75), outer_container
->bounds());
3033 EXPECT_EQ(gfx::SizeF(50, 75), active_tree
->ScrollableSize());
3034 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3037 // Fully hide the top controls.
3039 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3040 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3041 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3042 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3043 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3046 // Scrolling additionally shouldn't have any effect.
3048 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3049 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3050 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3051 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3052 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3055 host_impl_
->top_controls_manager()->ScrollEnd();
3056 host_impl_
->ScrollEnd();
3059 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
3060 SetupTopControlsAndScrollLayerWithVirtualViewport(
3061 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
3064 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3065 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3067 // Make the test scroll delta a fractional amount, to verify that the
3068 // fixed container size delta is (1) non-zero, and (2) fractional, and
3069 // (3) matches the movement of the top controls.
3070 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
3071 host_impl_
->top_controls_manager()->ScrollBegin();
3072 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3073 host_impl_
->top_controls_manager()->ScrollEnd();
3075 LayerImpl
* inner_viewport_scroll_layer
=
3076 host_impl_
->active_tree()->InnerViewportScrollLayer();
3077 DCHECK(inner_viewport_scroll_layer
);
3078 host_impl_
->ScrollEnd();
3079 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3080 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3083 // In this test, the outer viewport is initially unscrollable. We test that a
3084 // scroll initiated on the inner viewport, causing the top controls to show and
3085 // thus making the outer viewport scrollable, still scrolls the outer viewport.
3086 TEST_F(LayerTreeHostImplTopControlsTest
,
3087 TopControlsOuterViewportBecomesScrollable
) {
3088 SetupTopControlsAndScrollLayerWithVirtualViewport(
3089 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
3092 LayerImpl
* inner_scroll
=
3093 host_impl_
->active_tree()->InnerViewportScrollLayer();
3094 LayerImpl
* inner_container
=
3095 host_impl_
->active_tree()->InnerViewportContainerLayer();
3096 LayerImpl
* outer_scroll
=
3097 host_impl_
->active_tree()->OuterViewportScrollLayer();
3098 LayerImpl
* outer_container
=
3099 host_impl_
->active_tree()->OuterViewportContainerLayer();
3101 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
3102 outer_scroll
->SetDrawsContent(true);
3103 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
3105 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3106 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3107 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
3109 // The entire scroll delta should have been used to hide the top controls.
3110 // The viewport layers should be resized back to their full sizes.
3111 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3112 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3113 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
3114 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
3116 // The inner viewport should be scrollable by 50px * page_scale.
3117 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
3118 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
3119 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3120 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
3122 host_impl_
->ScrollEnd();
3124 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3125 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3126 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
3128 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3130 // The entire scroll delta should have been used to show the top controls.
3131 // The outer viewport should be resized to accomodate and scrolled to the
3132 // bottom of the document to keep the viewport in place.
3133 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3134 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
3135 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
3136 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3137 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3139 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3140 // since it wasn't scrollable when the scroll began.
3141 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
3142 EXPECT_EQ(15.f
, outer_scroll
->CurrentScrollOffset().y());
3143 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3145 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
3146 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3147 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3149 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3150 host_impl_
->ScrollEnd();
3152 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3153 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3156 // Test that the fixed position container delta is appropriately adjusted
3157 // by the top controls showing/hiding and page scale doesn't affect it.
3158 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
3159 SetupTopControlsAndScrollLayerWithVirtualViewport(
3160 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3162 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3164 float page_scale
= 1.5f
;
3165 LayerImpl
* outer_viewport_scroll_layer
=
3166 host_impl_
->active_tree()->OuterViewportScrollLayer();
3168 // Zoom in, since the fixed container is the outer viewport, the delta should
3170 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3172 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3173 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3175 // Scroll down, the top controls hiding should expand the viewport size so
3176 // the delta should be equal to the scroll distance.
3177 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
3178 host_impl_
->top_controls_manager()->ScrollBegin();
3179 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3180 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
3181 host_impl_
->top_controls_manager()->ContentTopOffset());
3182 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3183 outer_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3184 host_impl_
->ScrollEnd();
3186 // Scroll past the maximum extent. The delta shouldn't be greater than the
3187 // top controls height.
3188 host_impl_
->top_controls_manager()->ScrollBegin();
3189 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3190 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3191 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3192 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3193 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
3194 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3195 host_impl_
->ScrollEnd();
3197 // Scroll in the direction to make the top controls show.
3198 host_impl_
->top_controls_manager()->ScrollBegin();
3199 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
3200 EXPECT_EQ(top_controls_scroll_delta
.y(),
3201 host_impl_
->top_controls_manager()->ContentTopOffset());
3203 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
3204 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3205 host_impl_
->top_controls_manager()->ScrollEnd();
3208 // Test that if only the top controls are scrolled, we shouldn't request a
3210 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsDontTriggerCommit
) {
3211 SetupTopControlsAndScrollLayerWithVirtualViewport(
3212 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3215 // Show top controls
3216 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3218 // Scroll 25px to hide top controls
3219 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3220 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3221 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3222 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3223 EXPECT_FALSE(did_request_commit_
);
3226 // Test that if a scrollable sublayer doesn't consume the scroll,
3227 // top controls should hide when scrolling down.
3228 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
3229 gfx::Size
sub_content_size(100, 400);
3230 gfx::Size
sub_content_layer_size(100, 300);
3231 SetupTopControlsAndScrollLayerWithVirtualViewport(
3232 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3235 // Show top controls
3236 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3238 LayerImpl
* outer_viewport_scroll_layer
=
3239 host_impl_
->active_tree()->OuterViewportScrollLayer();
3240 int id
= outer_viewport_scroll_layer
->id();
3242 scoped_ptr
<LayerImpl
> child
=
3243 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
3244 scoped_ptr
<LayerImpl
> child_clip
=
3245 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
3247 child_clip
->SetBounds(sub_content_layer_size
);
3248 child
->SetScrollClipLayer(child_clip
->id());
3249 child
->SetBounds(sub_content_size
);
3250 child
->SetPosition(gfx::PointF());
3251 child
->SetDrawsContent(true);
3252 child
->SetIsContainerForFixedPositionLayers(true);
3254 // scroll child to limit
3255 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
3256 child_clip
->AddChild(child
.Pass());
3257 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
3259 // Scroll 25px to hide top controls
3260 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3261 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3262 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3263 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3264 host_impl_
->ScrollEnd();
3266 // Top controls should be hidden
3267 EXPECT_EQ(scroll_delta
.y(),
3268 top_controls_height_
-
3269 host_impl_
->top_controls_manager()->ContentTopOffset());
3272 // Ensure setting the top controls position explicitly using the setters on the
3273 // TreeImpl correctly affects the top controls manager and viewport bounds.
3274 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
3275 CreateHostImpl(settings_
, CreateOutputSurface());
3276 SetupTopControlsAndScrollLayerWithVirtualViewport(
3277 layer_size_
, layer_size_
, layer_size_
);
3280 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3281 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3282 30.f
/ top_controls_height_
);
3283 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3284 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3285 EXPECT_FLOAT_EQ(-20.f
,
3286 host_impl_
->top_controls_manager()->ControlsTopOffset());
3288 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3289 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3290 EXPECT_FLOAT_EQ(-50.f
,
3291 host_impl_
->top_controls_manager()->ControlsTopOffset());
3293 host_impl_
->DidChangeTopControlsPosition();
3295 // Now that top controls have moved, expect the clip to resize.
3296 LayerImpl
* inner_clip_ptr
=
3297 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3298 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3301 // Test that the top_controls delta and sent delta are appropriately
3302 // applied on sync tree activation. The total top controls offset shouldn't
3303 // change after the activation.
3304 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
3305 CreateHostImpl(settings_
, CreateOutputSurface());
3306 SetupTopControlsAndScrollLayerWithVirtualViewport(
3307 layer_size_
, layer_size_
, layer_size_
);
3310 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3311 20.f
/ top_controls_height_
);
3312 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3313 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
3314 15.f
/ top_controls_height_
);
3315 host_impl_
->active_tree()
3316 ->top_controls_shown_ratio()
3317 ->PullDeltaForMainThread();
3318 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3319 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
3320 top_controls_height_
);
3322 host_impl_
->DidChangeTopControlsPosition();
3323 LayerImpl
* inner_clip_ptr
=
3324 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3325 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3326 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3328 host_impl_
->ActivateSyncTree();
3330 inner_clip_ptr
= host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3331 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3332 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3335 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
3336 top_controls_height_
);
3339 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3340 top_controls_height_
);
3343 // Test that changing the top controls layout height is correctly applied to
3344 // the inner viewport container bounds. That is, the top controls layout
3345 // height is the amount that the inner viewport container was shrunk outside
3346 // the compositor to accommodate the top controls.
3347 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
3348 CreateHostImpl(settings_
, CreateOutputSurface());
3349 SetupTopControlsAndScrollLayerWithVirtualViewport(
3350 layer_size_
, layer_size_
, layer_size_
);
3353 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
3354 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3356 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3358 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3359 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3361 host_impl_
->DidChangeTopControlsPosition();
3362 LayerImpl
* inner_clip_ptr
=
3363 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3364 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3365 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3367 host_impl_
->sync_tree()->root_layer()->SetBounds(
3368 gfx::Size(inner_clip_ptr
->bounds().width(),
3369 inner_clip_ptr
->bounds().height() - 50.f
));
3371 host_impl_
->ActivateSyncTree();
3374 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3375 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3377 // The total bounds should remain unchanged since the bounds delta should
3378 // account for the difference between the layout height and the current
3379 // top controls offset.
3380 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3381 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), inner_clip_ptr
->bounds_delta());
3383 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3384 host_impl_
->DidChangeTopControlsPosition();
3386 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
3387 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
3388 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3389 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), inner_clip_ptr
->bounds_delta());
3390 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
3391 inner_clip_ptr
->bounds());
3394 // Test that showing/hiding the top controls when the viewport is fully scrolled
3395 // doesn't incorrectly change the viewport offset due to clamping from changing
3397 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
3398 SetupTopControlsAndScrollLayerWithVirtualViewport(
3399 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3402 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3404 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3405 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3407 // Scroll the viewports to max scroll offset.
3408 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3409 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3411 gfx::ScrollOffset viewport_offset
=
3412 host_impl_
->active_tree()->TotalScrollOffset();
3413 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
3415 // Hide the top controls by 25px.
3416 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3417 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3418 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3419 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3421 // scrolling down at the max extents no longer hides the top controls
3422 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3424 // forcefully hide the top controls by 25px
3425 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3426 host_impl_
->ScrollEnd();
3428 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3429 top_controls_height_
-
3430 host_impl_
->top_controls_manager()->ContentTopOffset());
3432 inner_scroll
->ClampScrollToMaxScrollOffset();
3433 outer_scroll
->ClampScrollToMaxScrollOffset();
3435 // We should still be fully scrolled.
3436 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3437 host_impl_
->active_tree()->TotalScrollOffset());
3439 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3441 // Bring the top controls down by 25px.
3442 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3443 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3444 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3445 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3446 host_impl_
->ScrollEnd();
3448 // The viewport offset shouldn't have changed.
3449 EXPECT_EQ(viewport_offset
,
3450 host_impl_
->active_tree()->TotalScrollOffset());
3452 // Scroll the viewports to max scroll offset.
3453 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3454 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3455 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3456 host_impl_
->active_tree()->TotalScrollOffset());
3459 // Test that the top controls coming in and out maintains the same aspect ratio
3460 // between the inner and outer viewports.
3461 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3462 SetupTopControlsAndScrollLayerWithVirtualViewport(
3463 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3464 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 2.f
);
3467 EXPECT_FLOAT_EQ(top_controls_height_
,
3468 host_impl_
->top_controls_manager()->ContentTopOffset());
3470 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3471 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3472 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3473 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3474 host_impl_
->ScrollEnd();
3476 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3477 top_controls_height_
-
3478 host_impl_
->top_controls_manager()->ContentTopOffset());
3480 // Top controls were hidden by 25px so the inner viewport should have expanded
3482 LayerImpl
* outer_container
=
3483 host_impl_
->active_tree()->OuterViewportContainerLayer();
3484 LayerImpl
* inner_container
=
3485 host_impl_
->active_tree()->InnerViewportContainerLayer();
3486 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3488 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3489 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3490 inner_container
->BoundsForScrolling().height();
3491 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3492 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3494 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3497 // Test that scrolling the outer viewport affects the top controls.
3498 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3499 SetupTopControlsAndScrollLayerWithVirtualViewport(
3500 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3503 EXPECT_EQ(top_controls_height_
,
3504 host_impl_
->top_controls_manager()->ContentTopOffset());
3506 // Send a gesture scroll that will scroll the outer viewport, make sure the
3507 // top controls get scrolled.
3508 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3509 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3510 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3511 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3512 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3513 host_impl_
->CurrentlyScrollingLayer());
3514 host_impl_
->ScrollEnd();
3516 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3517 top_controls_height_
-
3518 host_impl_
->top_controls_manager()->ContentTopOffset());
3520 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3521 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3522 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3523 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3525 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3526 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3527 host_impl_
->CurrentlyScrollingLayer());
3529 host_impl_
->ScrollEnd();
3531 // Position the viewports such that the inner viewport will be scrolled.
3532 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3533 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3534 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3536 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3537 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3538 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3539 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3541 EXPECT_EQ(top_controls_height_
,
3542 host_impl_
->top_controls_manager()->ContentTopOffset());
3544 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3545 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3547 host_impl_
->ScrollEnd();
3550 TEST_F(LayerTreeHostImplTopControlsTest
,
3551 ScrollNonScrollableRootWithTopControls
) {
3552 CreateHostImpl(settings_
, CreateOutputSurface());
3553 SetupTopControlsAndScrollLayerWithVirtualViewport(
3554 layer_size_
, layer_size_
, layer_size_
);
3557 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3558 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3560 host_impl_
->top_controls_manager()->ScrollBegin();
3561 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3562 host_impl_
->top_controls_manager()->ScrollEnd();
3563 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3564 // Now that top controls have moved, expect the clip to resize.
3565 LayerImpl
* inner_clip_ptr
=
3566 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3567 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3569 host_impl_
->ScrollEnd();
3571 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3572 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3574 float scroll_increment_y
= -25.f
;
3575 host_impl_
->top_controls_manager()->ScrollBegin();
3576 host_impl_
->top_controls_manager()->ScrollBy(
3577 gfx::Vector2dF(0.f
, scroll_increment_y
));
3578 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3579 host_impl_
->top_controls_manager()->ContentTopOffset());
3580 // Now that top controls have moved, expect the clip to resize.
3581 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3582 viewport_size_
.height() + scroll_increment_y
),
3583 inner_clip_ptr
->bounds());
3585 host_impl_
->top_controls_manager()->ScrollBy(
3586 gfx::Vector2dF(0.f
, scroll_increment_y
));
3587 host_impl_
->top_controls_manager()->ScrollEnd();
3588 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3589 host_impl_
->top_controls_manager()->ContentTopOffset());
3590 // Now that top controls have moved, expect the clip to resize.
3591 EXPECT_EQ(clip_size_
, inner_clip_ptr
->bounds());
3593 host_impl_
->ScrollEnd();
3595 // Verify the layer is once-again non-scrollable.
3597 gfx::ScrollOffset(),
3598 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3600 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3601 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3604 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3605 // Test the configuration where a non-composited root layer is embedded in a
3606 // scrollable outer layer.
3607 gfx::Size
surface_size(10, 10);
3608 gfx::Size
contents_size(20, 20);
3610 scoped_ptr
<LayerImpl
> content_layer
=
3611 LayerImpl::Create(host_impl_
->active_tree(), 1);
3612 content_layer
->SetDrawsContent(true);
3613 content_layer
->SetPosition(gfx::PointF());
3614 content_layer
->SetBounds(contents_size
);
3616 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3617 LayerImpl::Create(host_impl_
->active_tree(), 3);
3618 scroll_clip_layer
->SetBounds(surface_size
);
3620 scoped_ptr
<LayerImpl
> scroll_layer
=
3621 LayerImpl::Create(host_impl_
->active_tree(), 2);
3622 scroll_layer
->SetScrollClipLayer(3);
3623 scroll_layer
->SetBounds(contents_size
);
3624 scroll_layer
->SetPosition(gfx::PointF());
3625 scroll_layer
->AddChild(content_layer
.Pass());
3626 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3628 scroll_clip_layer
->SetHasRenderSurface(true);
3629 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3630 host_impl_
->SetViewportSize(surface_size
);
3633 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3634 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3635 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3636 host_impl_
->ScrollEnd();
3637 EXPECT_TRUE(did_request_redraw_
);
3638 EXPECT_TRUE(did_request_commit_
);
3641 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3642 gfx::Size
surface_size(10, 10);
3643 gfx::Size
contents_size(20, 20);
3644 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3645 root
->SetBounds(surface_size
);
3646 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3647 root
->SetHasRenderSurface(true);
3648 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3649 host_impl_
->SetViewportSize(surface_size
);
3652 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3653 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3654 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3655 host_impl_
->ScrollEnd();
3656 EXPECT_TRUE(did_request_redraw_
);
3657 EXPECT_TRUE(did_request_commit_
);
3660 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3661 gfx::Size
surface_size(10, 10);
3662 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3663 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3664 root
->SetHasRenderSurface(true);
3665 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3666 host_impl_
->SetViewportSize(surface_size
);
3669 // Scroll event is ignored because the input coordinate is outside the layer
3671 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3672 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3673 EXPECT_FALSE(did_request_redraw_
);
3674 EXPECT_FALSE(did_request_commit_
);
3677 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3678 gfx::Size
surface_size(10, 10);
3679 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3680 root
->SetHasRenderSurface(true);
3681 scoped_ptr
<LayerImpl
> child
=
3682 CreateScrollableLayer(2, surface_size
, root
.get());
3683 host_impl_
->SetViewportSize(surface_size
);
3685 gfx::Transform matrix
;
3686 matrix
.RotateAboutXAxis(180.0);
3687 child
->SetTransform(matrix
);
3688 child
->SetDoubleSided(false);
3690 root
->AddChild(child
.Pass());
3691 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3694 // Scroll event is ignored because the scrollable layer is not facing the
3695 // viewer and there is nothing scrollable behind it.
3696 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3697 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3698 EXPECT_FALSE(did_request_redraw_
);
3699 EXPECT_FALSE(did_request_commit_
);
3702 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3703 gfx::Size
surface_size(10, 10);
3704 scoped_ptr
<LayerImpl
> clip_layer
=
3705 LayerImpl::Create(host_impl_
->active_tree(), 3);
3706 scoped_ptr
<LayerImpl
> content_layer
=
3707 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3708 content_layer
->SetShouldScrollOnMainThread(true);
3709 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3711 // Note: we can use the same clip layer for both since both calls to
3712 // CreateScrollableLayer() use the same surface size.
3713 scoped_ptr
<LayerImpl
> scroll_layer
=
3714 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3715 scroll_layer
->AddChild(content_layer
.Pass());
3716 clip_layer
->AddChild(scroll_layer
.Pass());
3717 clip_layer
->SetHasRenderSurface(true);
3719 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3720 host_impl_
->SetViewportSize(surface_size
);
3723 // Scrolling fails because the content layer is asking to be scrolled on the
3725 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3726 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3729 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3730 gfx::Size
viewport_size(10, 10);
3731 float page_scale
= 2.f
;
3733 SetupScrollAndContentsLayers(viewport_size
);
3735 // Setup the layers so that the outer viewport is scrollable.
3736 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3738 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3740 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3743 LayerImpl
* root_scroll
=
3744 host_impl_
->active_tree()->OuterViewportScrollLayer();
3745 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3747 gfx::Vector2d
scroll_delta(0, 10);
3748 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3749 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3750 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3751 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3752 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3753 host_impl_
->ScrollEnd();
3755 // Set new page scale from main thread.
3756 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3758 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3759 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3760 expected_scroll_delta
));
3762 // The scroll range should also have been updated.
3763 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3765 // The page scale delta remains constant because the impl thread did not
3767 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3770 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3771 gfx::Size
viewport_size(10, 10);
3772 float page_scale
= 2.f
;
3774 SetupScrollAndContentsLayers(viewport_size
);
3776 // Setup the layers so that the outer viewport is scrollable.
3777 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3779 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3781 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3784 LayerImpl
* root_scroll
=
3785 host_impl_
->active_tree()->OuterViewportScrollLayer();
3786 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3788 gfx::Vector2d
scroll_delta(0, 10);
3789 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3790 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3791 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3792 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3793 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3794 host_impl_
->ScrollEnd();
3796 // Set new page scale on impl thread by pinching.
3797 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3798 host_impl_
->PinchGestureBegin();
3799 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3800 host_impl_
->PinchGestureEnd();
3801 host_impl_
->ScrollEnd();
3804 // The scroll delta is not scaled because the main thread did not scale.
3805 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3806 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3807 expected_scroll_delta
));
3809 // The scroll range should also have been updated.
3810 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3812 // The page scale delta should match the new scale on the impl side.
3813 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3816 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3817 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3818 gfx::Size
surface_size(10, 10);
3819 float default_page_scale
= 1.f
;
3820 gfx::Transform default_page_scale_matrix
;
3821 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3823 float new_page_scale
= 2.f
;
3824 gfx::Transform new_page_scale_matrix
;
3825 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3827 // Create a normal scrollable root layer and another scrollable child layer.
3828 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3829 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3830 LayerImpl
* child
= scroll
->children()[0];
3832 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3833 LayerImpl::Create(host_impl_
->active_tree(), 6);
3834 scoped_ptr
<LayerImpl
> scrollable_child
=
3835 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3836 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3837 child
->AddChild(scrollable_child_clip
.Pass());
3838 LayerImpl
* grand_child
= child
->children()[0];
3840 // Set new page scale on impl thread by pinching.
3841 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3842 host_impl_
->PinchGestureBegin();
3843 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3844 host_impl_
->PinchGestureEnd();
3845 host_impl_
->ScrollEnd();
3848 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3849 // the page scale delta on the root layer is applied hierarchically.
3850 LayerTreeHostImpl::FrameData frame
;
3851 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3852 host_impl_
->DrawLayers(&frame
);
3853 host_impl_
->DidDrawAllLayers(frame
);
3855 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3856 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3857 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3858 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3859 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3860 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3861 EXPECT_EQ(new_page_scale
,
3862 grand_child
->draw_transform().matrix().getDouble(0, 0));
3863 EXPECT_EQ(new_page_scale
,
3864 grand_child
->draw_transform().matrix().getDouble(1, 1));
3867 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3868 gfx::Size
surface_size(30, 30);
3869 SetupScrollAndContentsLayers(surface_size
);
3871 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3873 // Make the outer scroll layer scrollable.
3874 outer_scroll
->SetBounds(gfx::Size(50, 50));
3878 gfx::Vector2d
scroll_delta(0, 10);
3879 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3880 gfx::ScrollOffset
expected_max_scroll(outer_scroll
->MaxScrollOffset());
3881 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3882 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3883 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3884 host_impl_
->ScrollEnd();
3886 float page_scale
= 2.f
;
3887 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3892 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3893 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), outer_scroll
->id(),
3894 expected_scroll_delta
));
3896 // The scroll range should not have changed.
3897 EXPECT_EQ(outer_scroll
->MaxScrollOffset(), expected_max_scroll
);
3899 // The page scale delta remains constant because the impl thread did not
3901 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3904 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
3905 // Scroll a child layer beyond its maximum scroll range and make sure the
3906 // parent layer is scrolled on the axis on which the child was unable to
3908 gfx::Size
surface_size(10, 10);
3909 gfx::Size
content_size(20, 20);
3910 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3911 root
->SetBounds(surface_size
);
3912 root
->SetHasRenderSurface(true);
3913 scoped_ptr
<LayerImpl
> grand_child
=
3914 CreateScrollableLayer(3, content_size
, root
.get());
3916 scoped_ptr
<LayerImpl
> child
=
3917 CreateScrollableLayer(2, content_size
, root
.get());
3918 LayerImpl
* grand_child_layer
= grand_child
.get();
3919 child
->AddChild(grand_child
.Pass());
3921 LayerImpl
* child_layer
= child
.get();
3922 root
->AddChild(child
.Pass());
3923 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3924 host_impl_
->active_tree()->DidBecomeActive();
3925 host_impl_
->SetViewportSize(surface_size
);
3926 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3927 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3931 gfx::Vector2d
scroll_delta(-8, -7);
3932 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3933 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3934 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3935 host_impl_
->ScrollEnd();
3937 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3938 host_impl_
->ProcessScrollDeltas();
3940 // The grand child should have scrolled up to its limit.
3941 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
3942 LayerImpl
* grand_child
= child
->children()[0];
3943 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3944 gfx::Vector2d(0, -5)));
3946 // The child should have only scrolled on the other axis.
3947 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
3948 gfx::Vector2d(-3, 0)));
3952 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
3953 // Scroll a child layer beyond its maximum scroll range and make sure the
3954 // the scroll doesn't bubble up to the parent layer.
3955 gfx::Size
surface_size(20, 20);
3956 gfx::Size
viewport_size(10, 10);
3957 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3958 root
->SetHasRenderSurface(true);
3959 scoped_ptr
<LayerImpl
> root_scrolling
=
3960 CreateScrollableLayer(2, surface_size
, root
.get());
3961 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3963 scoped_ptr
<LayerImpl
> grand_child
=
3964 CreateScrollableLayer(4, surface_size
, root
.get());
3966 scoped_ptr
<LayerImpl
> child
=
3967 CreateScrollableLayer(3, surface_size
, root
.get());
3968 LayerImpl
* grand_child_layer
= grand_child
.get();
3969 child
->AddChild(grand_child
.Pass());
3971 LayerImpl
* child_layer
= child
.get();
3972 root_scrolling
->AddChild(child
.Pass());
3973 root
->AddChild(root_scrolling
.Pass());
3974 EXPECT_EQ(viewport_size
, root
->bounds());
3975 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3976 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3978 host_impl_
->active_tree()->DidBecomeActive();
3979 host_impl_
->SetViewportSize(viewport_size
);
3981 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3982 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3986 gfx::Vector2d
scroll_delta(0, -10);
3987 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3988 host_impl_
->ScrollBegin(gfx::Point(),
3989 InputHandler::NON_BUBBLING_GESTURE
));
3990 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3991 host_impl_
->ScrollEnd();
3993 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3994 host_impl_
->ProcessScrollDeltas();
3996 // The grand child should have scrolled up to its limit.
3998 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
3999 LayerImpl
* grand_child
= child
->children()[0];
4000 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4001 gfx::Vector2d(0, -2)));
4003 // The child should not have scrolled.
4004 ExpectNone(*scroll_info
.get(), child
->id());
4006 // The next time we scroll we should only scroll the parent.
4007 scroll_delta
= gfx::Vector2d(0, -3);
4008 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4009 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4010 InputHandler::NON_BUBBLING_GESTURE
));
4011 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4012 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4013 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
4014 host_impl_
->ScrollEnd();
4016 scroll_info
= host_impl_
->ProcessScrollDeltas();
4018 // The child should have scrolled up to its limit.
4019 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4020 gfx::Vector2d(0, -3)));
4022 // The grand child should not have scrolled.
4023 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4024 gfx::Vector2d(0, -2)));
4026 // After scrolling the parent, another scroll on the opposite direction
4027 // should still scroll the child.
4028 scroll_delta
= gfx::Vector2d(0, 7);
4029 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4030 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4031 InputHandler::NON_BUBBLING_GESTURE
));
4032 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4033 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4034 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4035 host_impl_
->ScrollEnd();
4037 scroll_info
= host_impl_
->ProcessScrollDeltas();
4039 // The grand child should have scrolled.
4040 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4041 gfx::Vector2d(0, 5)));
4043 // The child should not have scrolled.
4044 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4045 gfx::Vector2d(0, -3)));
4047 // Scrolling should be adjusted from viewport space.
4048 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
4049 host_impl_
->SetPageScaleOnActiveTree(2.f
);
4051 scroll_delta
= gfx::Vector2d(0, -2);
4052 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4053 host_impl_
->ScrollBegin(gfx::Point(1, 1),
4054 InputHandler::NON_BUBBLING_GESTURE
));
4055 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
4056 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4057 host_impl_
->ScrollEnd();
4059 scroll_info
= host_impl_
->ProcessScrollDeltas();
4061 // Should have scrolled by half the amount in layer space (5 - 2/2)
4062 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4063 gfx::Vector2d(0, 4)));
4066 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
4067 // When we try to scroll a non-scrollable child layer, the scroll delta
4068 // should be applied to one of its ancestors if possible.
4069 gfx::Size
surface_size(10, 10);
4070 gfx::Size
content_size(20, 20);
4071 scoped_ptr
<LayerImpl
> root_clip
=
4072 LayerImpl::Create(host_impl_
->active_tree(), 3);
4073 root_clip
->SetHasRenderSurface(true);
4074 scoped_ptr
<LayerImpl
> root
=
4075 CreateScrollableLayer(1, content_size
, root_clip
.get());
4076 // Make 'root' the clip layer for child: since they have the same sizes the
4077 // child will have zero max_scroll_offset and scrolls will bubble.
4078 scoped_ptr
<LayerImpl
> child
=
4079 CreateScrollableLayer(2, content_size
, root
.get());
4080 child
->SetIsContainerForFixedPositionLayers(true);
4081 root
->SetBounds(content_size
);
4083 int root_scroll_id
= root
->id();
4084 root
->AddChild(child
.Pass());
4085 root_clip
->AddChild(root
.Pass());
4087 host_impl_
->SetViewportSize(surface_size
);
4088 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4089 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
4091 host_impl_
->active_tree()->DidBecomeActive();
4094 gfx::Vector2d
scroll_delta(0, 4);
4095 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4096 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4097 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4098 host_impl_
->ScrollEnd();
4100 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4101 host_impl_
->ProcessScrollDeltas();
4103 // Only the root scroll should have scrolled.
4104 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
4106 ScrollInfoContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
));
4110 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
4111 gfx::Size
surface_size(10, 10);
4112 scoped_ptr
<LayerImpl
> root_clip
=
4113 LayerImpl::Create(host_impl_
->active_tree(), 1);
4114 scoped_ptr
<LayerImpl
> root_scroll
=
4115 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4116 root_scroll
->SetIsContainerForFixedPositionLayers(true);
4117 root_clip
->SetHasRenderSurface(true);
4118 root_clip
->AddChild(root_scroll
.Pass());
4119 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4120 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4122 host_impl_
->active_tree()->DidBecomeActive();
4123 host_impl_
->SetViewportSize(surface_size
);
4125 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4128 host_impl_
->active_tree()->DetachLayerTree();
4129 scoped_ptr
<LayerImpl
> root_clip2
=
4130 LayerImpl::Create(host_impl_
->active_tree(), 3);
4131 scoped_ptr
<LayerImpl
> root_scroll2
=
4132 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
4133 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
4134 root_clip2
->AddChild(root_scroll2
.Pass());
4135 root_clip2
->SetHasRenderSurface(true);
4136 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
4137 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
4139 host_impl_
->active_tree()->DidBecomeActive();
4141 // Scrolling should still work even though we did not draw yet.
4142 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4143 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4146 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
4147 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4149 // Rotate the root layer 90 degrees counter-clockwise about its center.
4150 gfx::Transform rotate_transform
;
4151 rotate_transform
.Rotate(-90.0);
4152 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
4154 gfx::Size
surface_size(50, 50);
4155 host_impl_
->SetViewportSize(surface_size
);
4158 // Scroll to the right in screen coordinates with a gesture.
4159 gfx::Vector2d
gesture_scroll_delta(10, 0);
4160 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4161 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4162 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4163 host_impl_
->ScrollEnd();
4165 // The layer should have scrolled down in its local coordinates.
4166 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4167 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4168 gfx::Vector2d(0, gesture_scroll_delta
.x())));
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 // The layer should have scrolled down in its local coordinates.
4179 scroll_info
= host_impl_
->ProcessScrollDeltas();
4180 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4181 wheel_scroll_delta
));
4184 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
4185 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4186 int child_clip_layer_id
= 6;
4187 int child_layer_id
= 7;
4188 float child_layer_angle
= -20.f
;
4190 // Create a child layer that is rotated to a non-axis-aligned angle.
4191 scoped_ptr
<LayerImpl
> clip_layer
=
4192 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4193 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4194 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4195 gfx::Transform rotate_transform
;
4196 rotate_transform
.Translate(-50.0, -50.0);
4197 rotate_transform
.Rotate(child_layer_angle
);
4198 rotate_transform
.Translate(50.0, 50.0);
4199 clip_layer
->SetTransform(rotate_transform
);
4201 // Only allow vertical scrolling.
4202 clip_layer
->SetBounds(
4203 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
4204 // The rotation depends on the layer's transform origin, and the child layer
4205 // is a different size than the clip, so make sure the clip layer's origin
4206 // lines up over the child.
4207 clip_layer
->SetTransformOrigin(gfx::Point3F(
4208 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
4209 LayerImpl
* child_ptr
= child
.get();
4210 clip_layer
->AddChild(child
.Pass());
4211 scroll_layer
->AddChild(clip_layer
.Pass());
4213 gfx::Size
surface_size(50, 50);
4214 host_impl_
->SetViewportSize(surface_size
);
4217 // Scroll down in screen coordinates with a gesture.
4218 gfx::Vector2d
gesture_scroll_delta(0, 10);
4219 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4220 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4221 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4222 host_impl_
->ScrollEnd();
4224 // The child layer should have scrolled down in its local coordinates an
4225 // amount proportional to the angle between it and the input scroll delta.
4226 gfx::Vector2d
expected_scroll_delta(
4227 0, gesture_scroll_delta
.y() *
4228 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
4229 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4230 host_impl_
->ProcessScrollDeltas();
4231 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4232 expected_scroll_delta
));
4234 // The root scroll layer should not have scrolled, because the input delta
4235 // was close to the layer's axis of movement.
4236 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4239 // Now reset and scroll the same amount horizontally.
4240 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4241 gfx::Vector2d
gesture_scroll_delta(10, 0);
4242 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4243 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4244 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4245 host_impl_
->ScrollEnd();
4247 // The child layer should have scrolled down in its local coordinates an
4248 // amount proportional to the angle between it and the input scroll delta.
4249 gfx::Vector2d
expected_scroll_delta(
4250 0, -gesture_scroll_delta
.x() *
4251 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
4252 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4253 host_impl_
->ProcessScrollDeltas();
4254 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4255 expected_scroll_delta
));
4257 // The root scroll layer should have scrolled more, since the input scroll
4258 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4259 gfx::Vector2d
expected_root_scroll_delta(
4260 gesture_scroll_delta
.x() *
4261 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
4263 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4264 expected_root_scroll_delta
));
4268 TEST_F(LayerTreeHostImplTest
, ScrollPerspectiveTransformedLayer
) {
4269 // When scrolling an element with perspective, the distance scrolled
4270 // depends on the point at which the scroll begins.
4271 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4272 int child_clip_layer_id
= 6;
4273 int child_layer_id
= 7;
4275 // Create a child layer that is rotated on its x axis, with perspective.
4276 scoped_ptr
<LayerImpl
> clip_layer
=
4277 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4278 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4279 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4280 LayerImpl
* child_ptr
= child
.get();
4281 gfx::Transform perspective_transform
;
4282 perspective_transform
.Translate(-50.0, -50.0);
4283 perspective_transform
.ApplyPerspectiveDepth(20);
4284 perspective_transform
.RotateAboutXAxis(45);
4285 perspective_transform
.Translate(50.0, 50.0);
4286 clip_layer
->SetTransform(perspective_transform
);
4288 clip_layer
->SetBounds(gfx::Size(child_ptr
->bounds().width() / 2,
4289 child_ptr
->bounds().height() / 2));
4290 // The transform depends on the layer's transform origin, and the child layer
4291 // is a different size than the clip, so make sure the clip layer's origin
4292 // lines up over the child.
4293 clip_layer
->SetTransformOrigin(gfx::Point3F(
4294 clip_layer
->bounds().width(), clip_layer
->bounds().height(), 0.f
));
4295 clip_layer
->AddChild(child
.Pass());
4296 scroll_layer
->AddChild(clip_layer
.Pass());
4298 gfx::Size
surface_size(50, 50);
4299 host_impl_
->SetViewportSize(surface_size
);
4301 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
4303 gfx::Vector2d gesture_scroll_deltas
[4];
4304 gesture_scroll_deltas
[0] = gfx::Vector2d(4, 10);
4305 gesture_scroll_deltas
[1] = gfx::Vector2d(4, 10);
4306 gesture_scroll_deltas
[2] = gfx::Vector2d(10, 0);
4307 gesture_scroll_deltas
[3] = gfx::Vector2d(10, 0);
4309 gfx::Vector2d expected_scroll_deltas
[4];
4310 // Perspective affects the vertical delta by a different
4311 // amount depending on the vertical position of the |viewport_point|.
4312 expected_scroll_deltas
[0] = gfx::Vector2d(2, 8);
4313 expected_scroll_deltas
[1] = gfx::Vector2d(1, 4);
4314 // Deltas which start with the same vertical position of the
4315 // |viewport_point| are subject to identical perspective effects.
4316 expected_scroll_deltas
[2] = gfx::Vector2d(4, 0);
4317 expected_scroll_deltas
[3] = gfx::Vector2d(4, 0);
4319 gfx::Point
viewport_point(1, 1);
4321 // Scroll in screen coordinates with a gesture. Each scroll starts
4322 // where the previous scroll ended, but the scroll position is reset
4324 for (int i
= 0; i
< 4; ++i
) {
4325 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4327 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4328 host_impl_
->ScrollBegin(viewport_point
, InputHandler::GESTURE
));
4329 host_impl_
->ScrollBy(viewport_point
, gesture_scroll_deltas
[i
]);
4330 viewport_point
+= gesture_scroll_deltas
[i
];
4331 host_impl_
->ScrollEnd();
4333 scroll_info
= host_impl_
->ProcessScrollDeltas();
4334 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4335 expected_scroll_deltas
[i
]));
4337 // The root scroll layer should not have scrolled, because the input delta
4338 // was close to the layer's axis of movement.
4339 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4343 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
4344 LayerImpl
* scroll_layer
=
4345 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4347 // Scale the layer to twice its normal size.
4349 gfx::Transform scale_transform
;
4350 scale_transform
.Scale(scale
, scale
);
4351 scroll_layer
->SetTransform(scale_transform
);
4353 gfx::Size
surface_size(50, 50);
4354 host_impl_
->SetViewportSize(surface_size
);
4357 // Scroll down in screen coordinates with a gesture.
4358 gfx::Vector2d
scroll_delta(0, 10);
4359 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4360 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4361 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4362 host_impl_
->ScrollEnd();
4364 // The layer should have scrolled down in its local coordinates, but half the
4366 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4367 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4368 gfx::Vector2d(0, scroll_delta
.y() / scale
)));
4370 // Reset and scroll down with the wheel.
4371 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4372 gfx::Vector2d
wheel_scroll_delta(0, 10);
4373 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4374 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4375 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4376 host_impl_
->ScrollEnd();
4378 // It should apply the scale factor to the scroll delta for the wheel event.
4379 scroll_info
= host_impl_
->ProcessScrollDeltas();
4380 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4381 wheel_scroll_delta
));
4384 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
4388 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
4389 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
4390 gfx::Size(width
* scale
- 1, height
* scale
));
4391 host_impl_
->SetDeviceScaleFactor(scale
);
4392 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4394 LayerImpl
* inner_viewport_scroll_layer
=
4395 host_impl_
->active_tree()->InnerViewportScrollLayer();
4396 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4397 inner_viewport_scroll_layer
->MaxScrollOffset());
4400 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
4402 TestScrollOffsetDelegate()
4403 : page_scale_factor_(0.f
),
4404 min_page_scale_factor_(-1.f
),
4405 max_page_scale_factor_(-1.f
),
4406 needs_animate_(false) {}
4408 ~TestScrollOffsetDelegate() override
{}
4410 gfx::ScrollOffset
GetTotalScrollOffset() override
{
4411 return getter_return_value_
;
4414 bool IsExternalScrollActive() const override
{ return false; }
4416 void SetNeedsAnimate(const AnimationCallback
&) override
{
4417 needs_animate_
= true;
4420 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
4421 const gfx::ScrollOffset
& max_scroll_offset
,
4422 const gfx::SizeF
& scrollable_size
,
4423 float page_scale_factor
,
4424 float min_page_scale_factor
,
4425 float max_page_scale_factor
) override
{
4426 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
4427 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
4428 last_set_scroll_offset_
= total_scroll_offset
;
4429 max_scroll_offset_
= max_scroll_offset
;
4430 scrollable_size_
= scrollable_size
;
4431 page_scale_factor_
= page_scale_factor
;
4432 min_page_scale_factor_
= min_page_scale_factor
;
4433 max_page_scale_factor_
= max_page_scale_factor
;
4435 set_getter_return_value(last_set_scroll_offset_
);
4438 bool GetAndResetNeedsAnimate() {
4439 bool needs_animate
= needs_animate_
;
4440 needs_animate_
= false;
4441 return needs_animate
;
4444 gfx::ScrollOffset
last_set_scroll_offset() {
4445 return last_set_scroll_offset_
;
4448 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
4449 getter_return_value_
= value
;
4452 gfx::ScrollOffset
max_scroll_offset() const {
4453 return max_scroll_offset_
;
4456 gfx::SizeF
scrollable_size() const {
4457 return scrollable_size_
;
4460 float page_scale_factor() const {
4461 return page_scale_factor_
;
4464 float min_page_scale_factor() const {
4465 return min_page_scale_factor_
;
4468 float max_page_scale_factor() const {
4469 return max_page_scale_factor_
;
4473 gfx::ScrollOffset last_set_scroll_offset_
;
4474 gfx::ScrollOffset getter_return_value_
;
4475 gfx::ScrollOffset max_scroll_offset_
;
4476 gfx::SizeF scrollable_size_
;
4477 float page_scale_factor_
;
4478 float min_page_scale_factor_
;
4479 float max_page_scale_factor_
;
4480 bool needs_animate_
;
4483 // TODO(jdduke): Test root fling animation.
4484 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4485 TestScrollOffsetDelegate scroll_delegate
;
4486 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4487 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4488 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4489 clip_layer
->SetBounds(gfx::Size(10, 20));
4491 // Setting the delegate results in the current scroll offset being set.
4492 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4493 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4494 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4495 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4496 EXPECT_EQ(initial_scroll_delta
.ToString(),
4497 scroll_delegate
.last_set_scroll_offset().ToString());
4499 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4500 // page_scale_factor and {min|max}_page_scale_factor being set.
4501 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4502 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4503 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4504 EXPECT_EQ(1.f
, scroll_delegate
.min_page_scale_factor());
4505 EXPECT_EQ(1.f
, scroll_delegate
.max_page_scale_factor());
4507 // Updating page scale immediately updates the delegate.
4508 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4509 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4510 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4511 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4512 host_impl_
->SetPageScaleOnActiveTree(2.f
* 1.5f
);
4513 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
4514 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4515 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4516 host_impl_
->SetPageScaleOnActiveTree(2.f
);
4517 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4518 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4519 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4520 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4522 // The pinch gesture doesn't put the delegate into a state where the scroll
4523 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4525 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4526 host_impl_
->PinchGestureBegin();
4527 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4528 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4529 host_impl_
->PinchGestureEnd();
4530 host_impl_
->ScrollEnd();
4532 // Scrolling should be relative to the offset as returned by the delegate.
4533 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4534 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4536 scroll_delegate
.set_getter_return_value(current_offset
);
4537 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4538 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4539 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4541 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4542 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4543 scroll_delegate
.last_set_scroll_offset());
4545 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4546 scroll_delegate
.set_getter_return_value(current_offset
);
4547 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4548 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4549 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4550 scroll_delegate
.last_set_scroll_offset());
4551 host_impl_
->ScrollEnd();
4552 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
4553 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4555 // Forces a full tree synchronization and ensures that the scroll delegate
4556 // sees the correct size of the new tree.
4557 gfx::Size
new_size(42, 24);
4558 host_impl_
->CreatePendingTree();
4559 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
4560 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4561 host_impl_
->ActivateSyncTree();
4562 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4564 // Un-setting the delegate should propagate the delegate's current offset to
4565 // the root scrollable layer.
4566 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4567 scroll_delegate
.set_getter_return_value(current_offset
);
4568 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4569 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4571 EXPECT_EQ(current_offset
.ToString(),
4572 scroll_layer
->CurrentScrollOffset().ToString());
4575 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4576 const gfx::Transform target_space_transform
=
4577 layer
->draw_properties().target_space_transform
;
4578 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4579 gfx::Point translated_point
;
4580 target_space_transform
.TransformPoint(&translated_point
);
4581 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4582 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4585 TEST_F(LayerTreeHostImplTest
,
4586 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4587 TestScrollOffsetDelegate scroll_delegate
;
4588 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4589 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4590 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4591 clip_layer
->SetBounds(gfx::Size(10, 20));
4592 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4594 // Draw first frame to clear any pending draws and check scroll.
4596 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4597 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4599 // Set external scroll delta on delegate and notify LayerTreeHost.
4600 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4601 scroll_delegate
.set_getter_return_value(scroll_offset
);
4602 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4604 // Check scroll delta reflected in layer.
4605 LayerTreeHostImpl::FrameData frame
;
4606 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4607 host_impl_
->DrawLayers(&frame
);
4608 host_impl_
->DidDrawAllLayers(frame
);
4609 EXPECT_FALSE(frame
.has_no_damage
);
4610 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4612 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4615 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4616 InputHandlerScrollResult scroll_result
;
4617 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4618 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4619 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4621 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4623 // In-bounds scrolling does not affect overscroll.
4624 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4625 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4626 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4627 EXPECT_TRUE(scroll_result
.did_scroll
);
4628 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4629 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4630 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4632 // Overscroll events are reflected immediately.
4633 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4634 EXPECT_TRUE(scroll_result
.did_scroll
);
4635 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4636 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4637 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4638 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4639 host_impl_
->accumulated_root_overscroll());
4641 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4642 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4643 EXPECT_TRUE(scroll_result
.did_scroll
);
4644 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4645 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4646 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4647 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4648 host_impl_
->accumulated_root_overscroll());
4650 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4651 EXPECT_FALSE(scroll_result
.did_scroll
);
4652 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4653 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4654 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4655 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4656 host_impl_
->accumulated_root_overscroll());
4658 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4659 EXPECT_TRUE(scroll_result
.did_scroll
);
4660 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4661 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4662 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4663 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4664 host_impl_
->accumulated_root_overscroll());
4666 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4667 EXPECT_TRUE(scroll_result
.did_scroll
);
4668 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4669 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4670 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4671 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4672 host_impl_
->accumulated_root_overscroll());
4674 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4675 EXPECT_TRUE(scroll_result
.did_scroll
);
4676 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4677 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4678 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4679 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4680 host_impl_
->accumulated_root_overscroll());
4682 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4683 EXPECT_TRUE(scroll_result
.did_scroll
);
4684 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4685 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4686 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4687 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4688 host_impl_
->accumulated_root_overscroll());
4690 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4691 // as no scroll occurs.
4692 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4693 EXPECT_FALSE(scroll_result
.did_scroll
);
4694 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4695 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4696 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4697 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4698 host_impl_
->accumulated_root_overscroll());
4700 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4701 EXPECT_FALSE(scroll_result
.did_scroll
);
4702 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4703 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4704 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4705 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4706 host_impl_
->accumulated_root_overscroll());
4708 // Overscroll resets on valid scroll.
4709 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4710 EXPECT_TRUE(scroll_result
.did_scroll
);
4711 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4712 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4713 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4714 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4715 host_impl_
->accumulated_root_overscroll());
4717 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4718 EXPECT_TRUE(scroll_result
.did_scroll
);
4719 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4720 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4721 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4722 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4723 host_impl_
->accumulated_root_overscroll());
4725 host_impl_
->ScrollEnd();
4729 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4730 // Scroll child layers beyond their maximum scroll range and make sure root
4731 // overscroll does not accumulate.
4732 InputHandlerScrollResult scroll_result
;
4733 gfx::Size
surface_size(10, 10);
4734 scoped_ptr
<LayerImpl
> root_clip
=
4735 LayerImpl::Create(host_impl_
->active_tree(), 4);
4736 root_clip
->SetHasRenderSurface(true);
4738 scoped_ptr
<LayerImpl
> root
=
4739 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4741 scoped_ptr
<LayerImpl
> grand_child
=
4742 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4744 scoped_ptr
<LayerImpl
> child
=
4745 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4746 LayerImpl
* grand_child_layer
= grand_child
.get();
4747 child
->AddChild(grand_child
.Pass());
4749 LayerImpl
* child_layer
= child
.get();
4750 root
->AddChild(child
.Pass());
4751 root_clip
->AddChild(root
.Pass());
4752 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4753 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4754 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4755 host_impl_
->active_tree()->DidBecomeActive();
4756 host_impl_
->SetViewportSize(surface_size
);
4759 gfx::Vector2d
scroll_delta(0, -10);
4760 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4761 host_impl_
->ScrollBegin(gfx::Point(),
4762 InputHandler::NON_BUBBLING_GESTURE
));
4763 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4764 EXPECT_TRUE(scroll_result
.did_scroll
);
4765 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4766 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4767 host_impl_
->ScrollEnd();
4769 // The next time we scroll we should only scroll the parent, but overscroll
4770 // should still not reach the root layer.
4771 scroll_delta
= gfx::Vector2d(0, -30);
4772 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4773 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4774 InputHandler::NON_BUBBLING_GESTURE
));
4775 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4776 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4777 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4778 EXPECT_TRUE(scroll_result
.did_scroll
);
4779 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4780 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4781 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4782 host_impl_
->ScrollEnd();
4784 // After scrolling the parent, another scroll on the opposite direction
4785 // should scroll the child.
4786 scroll_delta
= gfx::Vector2d(0, 70);
4787 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4788 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4789 InputHandler::NON_BUBBLING_GESTURE
));
4790 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4791 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4792 EXPECT_TRUE(scroll_result
.did_scroll
);
4793 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4794 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4795 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4796 host_impl_
->ScrollEnd();
4800 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4801 // When we try to scroll a non-scrollable child layer, the scroll delta
4802 // should be applied to one of its ancestors if possible. Overscroll should
4803 // be reflected only when it has bubbled up to the root scrolling layer.
4804 InputHandlerScrollResult scroll_result
;
4805 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4808 gfx::Vector2d
scroll_delta(0, 8);
4809 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4810 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4811 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4812 EXPECT_TRUE(scroll_result
.did_scroll
);
4813 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4814 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4815 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4816 EXPECT_TRUE(scroll_result
.did_scroll
);
4817 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4818 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4819 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4820 EXPECT_FALSE(scroll_result
.did_scroll
);
4821 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4822 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4823 host_impl_
->ScrollEnd();
4827 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4828 InputHandlerScrollResult scroll_result
;
4829 LayerTreeSettings settings
;
4830 CreateHostImpl(settings
, CreateOutputSurface());
4832 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4833 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4834 clip_layer
->SetBounds(gfx::Size(50, 50));
4835 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4836 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4838 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4840 // Even though the layer can't scroll the overscroll still happens.
4841 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4842 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4843 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4844 EXPECT_FALSE(scroll_result
.did_scroll
);
4845 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4846 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4849 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4850 InputHandlerScrollResult scroll_result
;
4851 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4855 // Edge glow effect should be applicable only upon reaching Edges
4856 // of the content. unnecessary glow effect calls shouldn't be
4857 // called while scrolling up without reaching the edge of the content.
4858 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4859 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4860 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4861 EXPECT_TRUE(scroll_result
.did_scroll
);
4862 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4863 EXPECT_EQ(gfx::Vector2dF().ToString(),
4864 host_impl_
->accumulated_root_overscroll().ToString());
4866 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4867 EXPECT_TRUE(scroll_result
.did_scroll
);
4868 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4869 EXPECT_EQ(gfx::Vector2dF().ToString(),
4870 host_impl_
->accumulated_root_overscroll().ToString());
4871 host_impl_
->ScrollEnd();
4872 // unusedrootDelta should be subtracted from applied delta so that
4873 // unwanted glow effect calls are not called.
4874 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4875 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4876 InputHandler::NON_BUBBLING_GESTURE
));
4877 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4878 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4879 EXPECT_TRUE(scroll_result
.did_scroll
);
4880 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4881 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4882 host_impl_
->accumulated_root_overscroll().ToString());
4885 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4886 EXPECT_FALSE(scroll_result
.did_scroll
);
4887 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4888 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4889 host_impl_
->accumulated_root_overscroll().ToString());
4890 host_impl_
->ScrollEnd();
4891 // TestCase to check kEpsilon, which prevents minute values to trigger
4892 // gloweffect without reaching edge.
4893 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4894 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4896 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4897 EXPECT_FALSE(scroll_result
.did_scroll
);
4898 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4899 EXPECT_EQ(gfx::Vector2dF().ToString(),
4900 host_impl_
->accumulated_root_overscroll().ToString());
4901 host_impl_
->ScrollEnd();
4905 class BlendStateCheckLayer
: public LayerImpl
{
4907 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4909 ResourceProvider
* resource_provider
) {
4910 return make_scoped_ptr(
4911 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4914 void AppendQuads(RenderPass
* render_pass
,
4915 AppendQuadsData
* append_quads_data
) override
{
4916 quads_appended_
= true;
4918 gfx::Rect opaque_rect
;
4919 if (contents_opaque())
4920 opaque_rect
= quad_rect_
;
4922 opaque_rect
= opaque_content_rect_
;
4923 gfx::Rect visible_quad_rect
= quad_rect_
;
4925 SharedQuadState
* shared_quad_state
=
4926 render_pass
->CreateAndAppendSharedQuadState();
4927 PopulateSharedQuadState(shared_quad_state
);
4929 TileDrawQuad
* test_blending_draw_quad
=
4930 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
4931 test_blending_draw_quad
->SetNew(shared_quad_state
,
4936 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4940 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
4941 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
4942 EXPECT_EQ(has_render_surface_
, !!render_surface());
4945 void SetExpectation(bool blend
, bool has_render_surface
) {
4947 has_render_surface_
= has_render_surface
;
4948 quads_appended_
= false;
4951 bool quads_appended() const { return quads_appended_
; }
4953 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
4954 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
4955 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
4956 opaque_content_rect_
= rect
;
4960 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
4962 ResourceProvider
* resource_provider
)
4963 : LayerImpl(tree_impl
, id
),
4965 has_render_surface_(false),
4966 quads_appended_(false),
4967 quad_rect_(5, 5, 5, 5),
4968 quad_visible_rect_(5, 5, 5, 5),
4969 resource_id_(resource_provider
->CreateResource(
4972 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
4974 resource_provider
->AllocateForTesting(resource_id_
);
4975 SetBounds(gfx::Size(10, 10));
4976 SetDrawsContent(true);
4980 bool has_render_surface_
;
4981 bool quads_appended_
;
4982 gfx::Rect quad_rect_
;
4983 gfx::Rect opaque_content_rect_
;
4984 gfx::Rect quad_visible_rect_
;
4985 ResourceId resource_id_
;
4988 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
4990 scoped_ptr
<LayerImpl
> root
=
4991 LayerImpl::Create(host_impl_
->active_tree(), 1);
4992 root
->SetBounds(gfx::Size(10, 10));
4993 root
->SetDrawsContent(false);
4994 root
->SetHasRenderSurface(true);
4995 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4997 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5000 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5002 host_impl_
->resource_provider()));
5003 BlendStateCheckLayer
* layer1
=
5004 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
5005 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
5007 LayerTreeHostImpl::FrameData frame
;
5009 // Opaque layer, drawn without blending.
5010 layer1
->SetContentsOpaque(true);
5011 layer1
->SetExpectation(false, false);
5012 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5013 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5014 host_impl_
->DrawLayers(&frame
);
5015 EXPECT_TRUE(layer1
->quads_appended());
5016 host_impl_
->DidDrawAllLayers(frame
);
5018 // Layer with translucent content and painting, so drawn with blending.
5019 layer1
->SetContentsOpaque(false);
5020 layer1
->SetExpectation(true, false);
5021 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5022 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5023 host_impl_
->DrawLayers(&frame
);
5024 EXPECT_TRUE(layer1
->quads_appended());
5025 host_impl_
->DidDrawAllLayers(frame
);
5027 // Layer with translucent opacity, drawn with blending.
5028 layer1
->SetContentsOpaque(true);
5029 layer1
->SetOpacity(0.5f
);
5030 layer1
->SetExpectation(true, false);
5031 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5032 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5033 host_impl_
->DrawLayers(&frame
);
5034 EXPECT_TRUE(layer1
->quads_appended());
5035 host_impl_
->DidDrawAllLayers(frame
);
5037 // Layer with translucent opacity and painting, drawn with blending.
5038 layer1
->SetContentsOpaque(true);
5039 layer1
->SetOpacity(0.5f
);
5040 layer1
->SetExpectation(true, false);
5041 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5042 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5043 host_impl_
->DrawLayers(&frame
);
5044 EXPECT_TRUE(layer1
->quads_appended());
5045 host_impl_
->DidDrawAllLayers(frame
);
5048 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5050 host_impl_
->resource_provider()));
5051 BlendStateCheckLayer
* layer2
=
5052 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
5053 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
5055 // 2 opaque layers, drawn without blending.
5056 layer1
->SetContentsOpaque(true);
5057 layer1
->SetOpacity(1.f
);
5058 layer1
->SetExpectation(false, false);
5059 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5060 layer2
->SetContentsOpaque(true);
5061 layer2
->SetOpacity(1.f
);
5062 layer2
->SetExpectation(false, false);
5063 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5064 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5065 host_impl_
->DrawLayers(&frame
);
5066 EXPECT_TRUE(layer1
->quads_appended());
5067 EXPECT_TRUE(layer2
->quads_appended());
5068 host_impl_
->DidDrawAllLayers(frame
);
5070 // Parent layer with translucent content, drawn with blending.
5071 // Child layer with opaque content, drawn without blending.
5072 layer1
->SetContentsOpaque(false);
5073 layer1
->SetExpectation(true, false);
5074 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5075 layer2
->SetExpectation(false, false);
5076 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5077 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5078 host_impl_
->DrawLayers(&frame
);
5079 EXPECT_TRUE(layer1
->quads_appended());
5080 EXPECT_TRUE(layer2
->quads_appended());
5081 host_impl_
->DidDrawAllLayers(frame
);
5083 // Parent layer with translucent content but opaque painting, drawn without
5085 // Child layer with opaque content, drawn without blending.
5086 layer1
->SetContentsOpaque(true);
5087 layer1
->SetExpectation(false, false);
5088 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5089 layer2
->SetExpectation(false, false);
5090 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5091 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5092 host_impl_
->DrawLayers(&frame
);
5093 EXPECT_TRUE(layer1
->quads_appended());
5094 EXPECT_TRUE(layer2
->quads_appended());
5095 host_impl_
->DidDrawAllLayers(frame
);
5097 // Parent layer with translucent opacity and opaque content. Since it has a
5098 // drawing child, it's drawn to a render surface which carries the opacity,
5099 // so it's itself drawn without blending.
5100 // Child layer with opaque content, drawn without blending (parent surface
5101 // carries the inherited opacity).
5102 layer1
->SetContentsOpaque(true);
5103 layer1
->SetOpacity(0.5f
);
5104 layer1
->SetHasRenderSurface(true);
5105 layer1
->SetExpectation(false, true);
5106 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5107 layer2
->SetExpectation(false, false);
5108 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5109 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5110 host_impl_
->active_tree()->root_layer());
5111 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5112 host_impl_
->DrawLayers(&frame
);
5113 EXPECT_TRUE(layer1
->quads_appended());
5114 EXPECT_TRUE(layer2
->quads_appended());
5115 host_impl_
->DidDrawAllLayers(frame
);
5116 layer1
->SetHasRenderSurface(false);
5118 // Draw again, but with child non-opaque, to make sure
5119 // layer1 not culled.
5120 layer1
->SetContentsOpaque(true);
5121 layer1
->SetOpacity(1.f
);
5122 layer1
->SetExpectation(false, false);
5123 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5124 layer2
->SetContentsOpaque(true);
5125 layer2
->SetOpacity(0.5f
);
5126 layer2
->SetExpectation(true, false);
5127 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5128 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5129 host_impl_
->DrawLayers(&frame
);
5130 EXPECT_TRUE(layer1
->quads_appended());
5131 EXPECT_TRUE(layer2
->quads_appended());
5132 host_impl_
->DidDrawAllLayers(frame
);
5134 // A second way of making the child non-opaque.
5135 layer1
->SetContentsOpaque(true);
5136 layer1
->SetOpacity(1.f
);
5137 layer1
->SetExpectation(false, false);
5138 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5139 layer2
->SetContentsOpaque(false);
5140 layer2
->SetOpacity(1.f
);
5141 layer2
->SetExpectation(true, false);
5142 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5143 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5144 host_impl_
->DrawLayers(&frame
);
5145 EXPECT_TRUE(layer1
->quads_appended());
5146 EXPECT_TRUE(layer2
->quads_appended());
5147 host_impl_
->DidDrawAllLayers(frame
);
5149 // And when the layer says its not opaque but is painted opaque, it is not
5151 layer1
->SetContentsOpaque(true);
5152 layer1
->SetOpacity(1.f
);
5153 layer1
->SetExpectation(false, false);
5154 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5155 layer2
->SetContentsOpaque(true);
5156 layer2
->SetOpacity(1.f
);
5157 layer2
->SetExpectation(false, false);
5158 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5159 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5160 host_impl_
->DrawLayers(&frame
);
5161 EXPECT_TRUE(layer1
->quads_appended());
5162 EXPECT_TRUE(layer2
->quads_appended());
5163 host_impl_
->DidDrawAllLayers(frame
);
5165 // Layer with partially opaque contents, drawn with blending.
5166 layer1
->SetContentsOpaque(false);
5167 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5168 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5169 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5170 layer1
->SetExpectation(true, false);
5171 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5172 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5173 host_impl_
->DrawLayers(&frame
);
5174 EXPECT_TRUE(layer1
->quads_appended());
5175 host_impl_
->DidDrawAllLayers(frame
);
5177 // Layer with partially opaque contents partially culled, drawn with blending.
5178 layer1
->SetContentsOpaque(false);
5179 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5180 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5181 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5182 layer1
->SetExpectation(true, false);
5183 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5184 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5185 host_impl_
->DrawLayers(&frame
);
5186 EXPECT_TRUE(layer1
->quads_appended());
5187 host_impl_
->DidDrawAllLayers(frame
);
5189 // Layer with partially opaque contents culled, drawn with blending.
5190 layer1
->SetContentsOpaque(false);
5191 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5192 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5193 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5194 layer1
->SetExpectation(true, false);
5195 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5196 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5197 host_impl_
->DrawLayers(&frame
);
5198 EXPECT_TRUE(layer1
->quads_appended());
5199 host_impl_
->DidDrawAllLayers(frame
);
5201 // Layer with partially opaque contents and translucent contents culled, drawn
5202 // without blending.
5203 layer1
->SetContentsOpaque(false);
5204 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5205 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5206 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5207 layer1
->SetExpectation(false, false);
5208 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5209 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5210 host_impl_
->DrawLayers(&frame
);
5211 EXPECT_TRUE(layer1
->quads_appended());
5212 host_impl_
->DidDrawAllLayers(frame
);
5215 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
5217 LayerTreeHostImplViewportCoveredTest() :
5218 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
5220 did_activate_pending_tree_(false) {}
5222 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
5224 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5226 return FakeOutputSurface::Create3d();
5229 void SetupActiveTreeLayers() {
5230 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
5231 host_impl_
->active_tree()->SetRootLayer(
5232 LayerImpl::Create(host_impl_
->active_tree(), 1));
5233 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
5234 host_impl_
->active_tree()->root_layer()->AddChild(
5235 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5237 host_impl_
->resource_provider()));
5238 child_
= static_cast<BlendStateCheckLayer
*>(
5239 host_impl_
->active_tree()->root_layer()->children()[0]);
5240 child_
->SetExpectation(false, false);
5241 child_
->SetContentsOpaque(true);
5244 // Expect no gutter rects.
5245 void TestLayerCoversFullViewport() {
5246 gfx::Rect
layer_rect(viewport_size_
);
5247 child_
->SetPosition(layer_rect
.origin());
5248 child_
->SetBounds(layer_rect
.size());
5249 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5250 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5252 LayerTreeHostImpl::FrameData frame
;
5253 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5254 ASSERT_EQ(1u, frame
.render_passes
.size());
5256 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5257 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5258 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5260 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5261 host_impl_
->DidDrawAllLayers(frame
);
5264 // Expect fullscreen gutter rect.
5265 void TestEmptyLayer() {
5266 gfx::Rect
layer_rect(0, 0, 0, 0);
5267 child_
->SetPosition(layer_rect
.origin());
5268 child_
->SetBounds(layer_rect
.size());
5269 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5270 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5272 LayerTreeHostImpl::FrameData frame
;
5273 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5274 ASSERT_EQ(1u, frame
.render_passes
.size());
5276 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5277 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5278 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5280 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5281 host_impl_
->DidDrawAllLayers(frame
);
5284 // Expect four surrounding gutter rects.
5285 void TestLayerInMiddleOfViewport() {
5286 gfx::Rect
layer_rect(500, 500, 200, 200);
5287 child_
->SetPosition(layer_rect
.origin());
5288 child_
->SetBounds(layer_rect
.size());
5289 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5290 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5292 LayerTreeHostImpl::FrameData frame
;
5293 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5294 ASSERT_EQ(1u, frame
.render_passes
.size());
5296 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5297 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
5298 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5300 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5301 host_impl_
->DidDrawAllLayers(frame
);
5304 // Expect no gutter rects.
5305 void TestLayerIsLargerThanViewport() {
5306 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
5307 viewport_size_
.height() + 10);
5308 child_
->SetPosition(layer_rect
.origin());
5309 child_
->SetBounds(layer_rect
.size());
5310 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5311 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5313 LayerTreeHostImpl::FrameData frame
;
5314 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5315 ASSERT_EQ(1u, frame
.render_passes
.size());
5317 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5318 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5319 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5321 host_impl_
->DidDrawAllLayers(frame
);
5324 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
5326 void set_gutter_quad_material(DrawQuad::Material material
) {
5327 gutter_quad_material_
= material
;
5329 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
5330 gutter_texture_size_
= gutter_texture_size
;
5334 size_t CountGutterQuads(const QuadList
& quad_list
) {
5335 size_t num_gutter_quads
= 0;
5336 for (const auto& quad
: quad_list
) {
5337 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
5339 return num_gutter_quads
;
5342 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
5343 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5344 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
5347 // Make sure that the texture coordinates match their expectations.
5348 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
5349 for (const auto& quad
: quad_list
) {
5350 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
5352 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
5353 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
5354 gutter_texture_size_
, host_impl_
->device_scale_factor());
5355 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
5356 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
5357 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
5358 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
5360 texture_quad
->uv_bottom_right
.x(),
5361 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
5363 texture_quad
->uv_bottom_right
.y(),
5364 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
5368 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
5369 return gfx::ToRoundedSize(
5370 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
5373 DrawQuad::Material gutter_quad_material_
;
5374 gfx::Size gutter_texture_size_
;
5375 gfx::Size viewport_size_
;
5376 BlendStateCheckLayer
* child_
;
5377 bool did_activate_pending_tree_
;
5380 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
5381 viewport_size_
= gfx::Size(1000, 1000);
5383 bool always_draw
= false;
5384 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5386 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5387 SetupActiveTreeLayers();
5388 TestLayerCoversFullViewport();
5390 TestLayerInMiddleOfViewport();
5391 TestLayerIsLargerThanViewport();
5394 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
5395 viewport_size_
= gfx::Size(1000, 1000);
5397 bool always_draw
= false;
5398 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5400 host_impl_
->SetDeviceScaleFactor(2.f
);
5401 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5402 SetupActiveTreeLayers();
5403 TestLayerCoversFullViewport();
5405 TestLayerInMiddleOfViewport();
5406 TestLayerIsLargerThanViewport();
5409 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
5410 viewport_size_
= gfx::Size(1000, 1000);
5412 bool always_draw
= true;
5413 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5415 // Pending tree to force active_tree size invalid. Not used otherwise.
5416 host_impl_
->CreatePendingTree();
5417 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5418 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5420 SetupActiveTreeLayers();
5422 TestLayerInMiddleOfViewport();
5423 TestLayerIsLargerThanViewport();
5426 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5427 viewport_size_
= gfx::Size(1000, 1000);
5429 bool always_draw
= true;
5430 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5432 // Set larger viewport and activate it to active tree.
5433 host_impl_
->CreatePendingTree();
5434 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5435 viewport_size_
.height() + 100);
5436 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5437 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5438 host_impl_
->ActivateSyncTree();
5439 EXPECT_TRUE(did_activate_pending_tree_
);
5440 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5442 // Shrink pending tree viewport without activating.
5443 host_impl_
->CreatePendingTree();
5444 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5445 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5447 SetupActiveTreeLayers();
5449 TestLayerInMiddleOfViewport();
5450 TestLayerIsLargerThanViewport();
5453 class FakeDrawableLayerImpl
: public LayerImpl
{
5455 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5456 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5459 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5460 : LayerImpl(tree_impl
, id
) {}
5463 // Only reshape when we know we are going to draw. Otherwise, the reshape
5464 // can leave the window at the wrong size if we never draw and the proper
5465 // viewport size is never set.
5466 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5467 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5468 scoped_ptr
<OutputSurface
> output_surface(
5469 FakeOutputSurface::Create3d(provider
));
5470 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5472 scoped_ptr
<LayerImpl
> root
=
5473 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5474 root
->SetBounds(gfx::Size(10, 10));
5475 root
->SetDrawsContent(true);
5476 root
->SetHasRenderSurface(true);
5477 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5478 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5479 provider
->TestContext3d()->clear_reshape_called();
5481 LayerTreeHostImpl::FrameData frame
;
5482 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5483 host_impl_
->SetDeviceScaleFactor(1.f
);
5484 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5485 host_impl_
->DrawLayers(&frame
);
5486 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5487 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5488 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5489 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5490 host_impl_
->DidDrawAllLayers(frame
);
5491 provider
->TestContext3d()->clear_reshape_called();
5493 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5494 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5495 host_impl_
->DrawLayers(&frame
);
5496 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5497 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5498 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5499 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5500 host_impl_
->DidDrawAllLayers(frame
);
5501 provider
->TestContext3d()->clear_reshape_called();
5503 host_impl_
->SetDeviceScaleFactor(2.f
);
5504 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5505 host_impl_
->DrawLayers(&frame
);
5506 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5507 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5508 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5509 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5510 host_impl_
->DidDrawAllLayers(frame
);
5511 provider
->TestContext3d()->clear_reshape_called();
5514 // Make sure damage tracking propagates all the way to the graphics context,
5515 // where it should request to swap only the sub-buffer that is damaged.
5516 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5517 scoped_refptr
<TestContextProvider
> context_provider(
5518 TestContextProvider::Create());
5519 context_provider
->BindToCurrentThread();
5520 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5522 scoped_ptr
<FakeOutputSurface
> output_surface(
5523 FakeOutputSurface::Create3d(context_provider
));
5524 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5526 // This test creates its own LayerTreeHostImpl, so
5527 // that we can force partial swap enabled.
5528 LayerTreeSettings settings
;
5529 settings
.renderer_settings
.partial_swap_enabled
= true;
5530 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5531 LayerTreeHostImpl::Create(
5532 settings
, this, &proxy_
, &stats_instrumentation_
,
5533 &shared_bitmap_manager_
, NULL
, &task_graph_runner_
, 0);
5534 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5535 layer_tree_host_impl
->WillBeginImplFrame(
5536 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5537 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5539 scoped_ptr
<LayerImpl
> root
=
5540 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5541 root
->SetHasRenderSurface(true);
5542 scoped_ptr
<LayerImpl
> child
=
5543 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5544 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5545 child
->SetBounds(gfx::Size(14, 15));
5546 child
->SetDrawsContent(true);
5547 root
->SetBounds(gfx::Size(500, 500));
5548 root
->SetDrawsContent(true);
5549 root
->AddChild(child
.Pass());
5550 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5552 LayerTreeHostImpl::FrameData frame
;
5554 // First frame, the entire screen should get swapped.
5555 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5556 layer_tree_host_impl
->DrawLayers(&frame
);
5557 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5558 layer_tree_host_impl
->SwapBuffers(frame
);
5559 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5560 EXPECT_EQ(expected_swap_rect
.ToString(),
5561 fake_output_surface
->last_swap_rect().ToString());
5563 // Second frame, only the damaged area should get swapped. Damage should be
5564 // the union of old and new child rects.
5565 // expected damage rect: gfx::Rect(26, 28);
5566 // expected swap rect: vertically flipped, with origin at bottom left corner.
5567 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5569 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5570 layer_tree_host_impl
->DrawLayers(&frame
);
5571 host_impl_
->DidDrawAllLayers(frame
);
5572 layer_tree_host_impl
->SwapBuffers(frame
);
5574 // Make sure that partial swap is constrained to the viewport dimensions
5575 // expected damage rect: gfx::Rect(500, 500);
5576 // expected swap rect: flipped damage rect, but also clamped to viewport
5577 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5578 EXPECT_EQ(expected_swap_rect
.ToString(),
5579 fake_output_surface
->last_swap_rect().ToString());
5581 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5582 // This will damage everything.
5583 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5585 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5586 layer_tree_host_impl
->DrawLayers(&frame
);
5587 host_impl_
->DidDrawAllLayers(frame
);
5588 layer_tree_host_impl
->SwapBuffers(frame
);
5590 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5591 EXPECT_EQ(expected_swap_rect
.ToString(),
5592 fake_output_surface
->last_swap_rect().ToString());
5595 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5596 scoped_ptr
<LayerImpl
> root
=
5597 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5598 scoped_ptr
<LayerImpl
> child
=
5599 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5600 child
->SetBounds(gfx::Size(10, 10));
5601 child
->SetDrawsContent(true);
5602 root
->SetBounds(gfx::Size(10, 10));
5603 root
->SetDrawsContent(true);
5604 root
->SetHasRenderSurface(true);
5605 root
->AddChild(child
.Pass());
5607 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5609 LayerTreeHostImpl::FrameData frame
;
5611 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5612 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5613 EXPECT_EQ(1u, frame
.render_passes
.size());
5614 host_impl_
->DidDrawAllLayers(frame
);
5617 class FakeLayerWithQuads
: public LayerImpl
{
5619 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5620 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5623 void AppendQuads(RenderPass
* render_pass
,
5624 AppendQuadsData
* append_quads_data
) override
{
5625 SharedQuadState
* shared_quad_state
=
5626 render_pass
->CreateAndAppendSharedQuadState();
5627 PopulateSharedQuadState(shared_quad_state
);
5629 SkColor gray
= SkColorSetRGB(100, 100, 100);
5630 gfx::Rect
quad_rect(bounds());
5631 gfx::Rect
visible_quad_rect(quad_rect
);
5632 SolidColorDrawQuad
* my_quad
=
5633 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5635 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5639 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5640 : LayerImpl(tree_impl
, id
) {}
5643 class MockContext
: public TestWebGraphicsContext3D
{
5645 MOCK_METHOD1(useProgram
, void(GLuint program
));
5646 MOCK_METHOD5(uniform4f
, void(GLint location
,
5651 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5653 GLboolean transpose
,
5654 const GLfloat
* value
));
5655 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5659 MOCK_METHOD1(enable
, void(GLenum cap
));
5660 MOCK_METHOD1(disable
, void(GLenum cap
));
5661 MOCK_METHOD4(scissor
, void(GLint x
,
5667 class MockContextHarness
{
5669 MockContext
* context_
;
5672 explicit MockContextHarness(MockContext
* context
)
5673 : context_(context
) {
5674 context_
->set_have_post_sub_buffer(true);
5676 // Catch "uninteresting" calls
5677 EXPECT_CALL(*context_
, useProgram(_
))
5680 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5683 // These are not asserted
5684 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5685 .WillRepeatedly(Return());
5687 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5688 .WillRepeatedly(Return());
5690 // Any un-sanctioned calls to enable() are OK
5691 EXPECT_CALL(*context_
, enable(_
))
5692 .WillRepeatedly(Return());
5694 // Any un-sanctioned calls to disable() are OK
5695 EXPECT_CALL(*context_
, disable(_
))
5696 .WillRepeatedly(Return());
5699 void MustDrawSolidQuad() {
5700 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5702 .RetiresOnSaturation();
5704 EXPECT_CALL(*context_
, useProgram(_
))
5706 .RetiresOnSaturation();
5709 void MustSetScissor(int x
, int y
, int width
, int height
) {
5710 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5711 .WillRepeatedly(Return());
5713 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5715 .WillRepeatedly(Return());
5718 void MustSetNoScissor() {
5719 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5720 .WillRepeatedly(Return());
5722 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5725 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5730 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5731 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5732 MockContext
* mock_context
= mock_context_owned
.get();
5733 MockContextHarness
harness(mock_context
);
5736 LayerTreeSettings settings
= DefaultSettings();
5737 settings
.renderer_settings
.partial_swap_enabled
= false;
5738 CreateHostImpl(settings
,
5739 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5740 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5742 // Without partial swap, and no clipping, no scissor is set.
5743 harness
.MustDrawSolidQuad();
5744 harness
.MustSetNoScissor();
5746 LayerTreeHostImpl::FrameData frame
;
5747 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5748 host_impl_
->DrawLayers(&frame
);
5749 host_impl_
->DidDrawAllLayers(frame
);
5751 Mock::VerifyAndClearExpectations(&mock_context
);
5753 // Without partial swap, but a layer does clip its subtree, one scissor is
5755 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5756 harness
.MustDrawSolidQuad();
5757 harness
.MustSetScissor(0, 0, 10, 10);
5759 LayerTreeHostImpl::FrameData frame
;
5760 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
5761 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5762 host_impl_
->DrawLayers(&frame
);
5763 host_impl_
->DidDrawAllLayers(frame
);
5765 Mock::VerifyAndClearExpectations(&mock_context
);
5768 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5769 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5770 MockContext
* mock_context
= context_owned
.get();
5771 MockContextHarness
harness(mock_context
);
5773 LayerTreeSettings settings
= DefaultSettings();
5774 settings
.renderer_settings
.partial_swap_enabled
= true;
5775 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5776 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5778 // The first frame is not a partially-swapped one. No scissor should be set.
5779 harness
.MustSetNoScissor();
5780 harness
.MustDrawSolidQuad();
5782 LayerTreeHostImpl::FrameData frame
;
5783 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5784 host_impl_
->DrawLayers(&frame
);
5785 host_impl_
->DidDrawAllLayers(frame
);
5787 Mock::VerifyAndClearExpectations(&mock_context
);
5789 // Damage a portion of the frame.
5790 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5791 gfx::Rect(0, 0, 2, 3));
5793 // The second frame will be partially-swapped (the y coordinates are flipped).
5794 harness
.MustSetScissor(0, 7, 2, 3);
5795 harness
.MustDrawSolidQuad();
5797 LayerTreeHostImpl::FrameData frame
;
5798 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5799 host_impl_
->DrawLayers(&frame
);
5800 host_impl_
->DidDrawAllLayers(frame
);
5802 Mock::VerifyAndClearExpectations(&mock_context
);
5805 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5807 LayerTreeHostImplClient
* client
,
5809 SharedBitmapManager
* manager
,
5810 TaskGraphRunner
* task_graph_runner
,
5811 RenderingStatsInstrumentation
* stats_instrumentation
) {
5812 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5813 scoped_ptr
<OutputSurface
> output_surface(
5814 FakeOutputSurface::Create3d(provider
));
5815 provider
->BindToCurrentThread();
5816 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5818 LayerTreeSettings settings
;
5819 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5820 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5821 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
,
5822 manager
, nullptr, task_graph_runner
, 0);
5823 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5824 my_host_impl
->WillBeginImplFrame(
5825 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5826 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5829 Layers are created as follows:
5831 +--------------------+
5835 | | +-------------------+
5837 | | +-------------------+
5842 +--------------------+
5844 Layers 1, 2 have render surfaces
5846 scoped_ptr
<LayerImpl
> root
=
5847 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5848 scoped_ptr
<LayerImpl
> child
=
5849 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5850 scoped_ptr
<LayerImpl
> grand_child
=
5851 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5853 gfx::Rect
root_rect(0, 0, 100, 100);
5854 gfx::Rect
child_rect(10, 10, 50, 50);
5855 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5857 root
->SetHasRenderSurface(true);
5858 root
->SetPosition(root_rect
.origin());
5859 root
->SetBounds(root_rect
.size());
5860 root
->draw_properties().visible_layer_rect
= root_rect
;
5861 root
->SetDrawsContent(false);
5862 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5864 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5865 child
->SetOpacity(0.5f
);
5866 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5867 child
->draw_properties().visible_layer_rect
= child_rect
;
5868 child
->SetDrawsContent(false);
5869 child
->SetHasRenderSurface(true);
5871 grand_child
->SetPosition(grand_child_rect
.origin());
5872 grand_child
->SetBounds(grand_child_rect
.size());
5873 grand_child
->draw_properties().visible_layer_rect
= grand_child_rect
;
5874 grand_child
->SetDrawsContent(true);
5876 child
->AddChild(grand_child
.Pass());
5877 root
->AddChild(child
.Pass());
5879 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5880 return my_host_impl
.Pass();
5883 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5884 TestSharedBitmapManager shared_bitmap_manager
;
5885 TestTaskGraphRunner task_graph_runner
;
5886 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5887 SetupLayersForOpacity(true, this, &proxy_
, &shared_bitmap_manager
,
5888 &task_graph_runner
, &stats_instrumentation_
);
5890 LayerTreeHostImpl::FrameData frame
;
5891 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5893 // Verify all quads have been computed
5894 ASSERT_EQ(2U, frame
.render_passes
.size());
5895 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5896 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5897 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5898 frame
.render_passes
[0]->quad_list
.front()->material
);
5899 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5900 frame
.render_passes
[1]->quad_list
.front()->material
);
5902 my_host_impl
->DrawLayers(&frame
);
5903 my_host_impl
->DidDrawAllLayers(frame
);
5907 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5908 TestSharedBitmapManager shared_bitmap_manager
;
5909 TestTaskGraphRunner task_graph_runner
;
5910 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5911 SetupLayersForOpacity(false, this, &proxy_
, &shared_bitmap_manager
,
5912 &task_graph_runner
, &stats_instrumentation_
);
5914 LayerTreeHostImpl::FrameData frame
;
5915 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5917 // Verify all quads have been computed
5918 ASSERT_EQ(2U, frame
.render_passes
.size());
5919 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5920 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5921 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5922 frame
.render_passes
[0]->quad_list
.front()->material
);
5923 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5924 frame
.render_passes
[1]->quad_list
.front()->material
);
5926 my_host_impl
->DrawLayers(&frame
);
5927 my_host_impl
->DidDrawAllLayers(frame
);
5931 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
5932 scoped_ptr
<TestWebGraphicsContext3D
> context
=
5933 TestWebGraphicsContext3D::Create();
5934 TestWebGraphicsContext3D
* context3d
= context
.get();
5935 scoped_ptr
<OutputSurface
> output_surface(
5936 FakeOutputSurface::Create3d(context
.Pass()));
5937 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5939 scoped_ptr
<LayerImpl
> root_layer
=
5940 LayerImpl::Create(host_impl_
->active_tree(), 1);
5941 root_layer
->SetBounds(gfx::Size(10, 10));
5942 root_layer
->SetHasRenderSurface(true);
5944 scoped_refptr
<VideoFrame
> softwareFrame
=
5945 media::VideoFrame::CreateColorFrame(
5946 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5947 FakeVideoFrameProvider provider
;
5948 provider
.set_frame(softwareFrame
);
5949 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5950 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
5951 video_layer
->SetBounds(gfx::Size(10, 10));
5952 video_layer
->SetDrawsContent(true);
5953 root_layer
->AddChild(video_layer
.Pass());
5955 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
5956 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
5957 io_surface_layer
->SetBounds(gfx::Size(10, 10));
5958 io_surface_layer
->SetDrawsContent(true);
5959 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5960 root_layer
->AddChild(io_surface_layer
.Pass());
5962 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
5964 EXPECT_EQ(0u, context3d
->NumTextures());
5966 LayerTreeHostImpl::FrameData frame
;
5967 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5968 host_impl_
->DrawLayers(&frame
);
5969 host_impl_
->DidDrawAllLayers(frame
);
5970 host_impl_
->SwapBuffers(frame
);
5972 EXPECT_GT(context3d
->NumTextures(), 0u);
5974 // Kill the layer tree.
5975 host_impl_
->active_tree()->SetRootLayer(
5976 LayerImpl::Create(host_impl_
->active_tree(), 100));
5977 // There should be no textures left in use after.
5978 EXPECT_EQ(0u, context3d
->NumTextures());
5981 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
5983 MOCK_METHOD1(useProgram
, void(GLuint program
));
5984 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5990 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
5991 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
5992 new MockDrawQuadsToFillScreenContext
);
5993 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
5996 LayerTreeSettings settings
= DefaultSettings();
5997 settings
.renderer_settings
.partial_swap_enabled
= false;
5998 CreateHostImpl(settings
,
5999 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
6000 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6001 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
6003 // Verify one quad is drawn when transparent background set is not set.
6004 host_impl_
->active_tree()->set_has_transparent_background(false);
6005 EXPECT_CALL(*mock_context
, useProgram(_
))
6007 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
6009 LayerTreeHostImpl::FrameData frame
;
6010 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6011 host_impl_
->DrawLayers(&frame
);
6012 host_impl_
->DidDrawAllLayers(frame
);
6013 Mock::VerifyAndClearExpectations(&mock_context
);
6015 // Verify no quads are drawn when transparent background is set.
6016 host_impl_
->active_tree()->set_has_transparent_background(true);
6017 host_impl_
->SetFullRootLayerDamage();
6018 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6019 host_impl_
->DrawLayers(&frame
);
6020 host_impl_
->DidDrawAllLayers(frame
);
6021 Mock::VerifyAndClearExpectations(&mock_context
);
6024 class LayerTreeHostImplTestWithDelegatingRenderer
6025 : public LayerTreeHostImplTest
{
6027 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
6028 return FakeOutputSurface::CreateDelegating3d();
6031 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
6032 bool expect_to_draw
= !expected_damage
.IsEmpty();
6034 LayerTreeHostImpl::FrameData frame
;
6035 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6037 if (!expect_to_draw
) {
6038 // With no damage, we don't draw, and no quads are created.
6039 ASSERT_EQ(0u, frame
.render_passes
.size());
6041 ASSERT_EQ(1u, frame
.render_passes
.size());
6043 // Verify the damage rect for the root render pass.
6044 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
6045 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
6047 // Verify the root and child layers' quads are generated and not being
6049 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
6051 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
6052 gfx::RectF
expected_child_visible_rect(child
->bounds());
6053 EXPECT_EQ(expected_child_visible_rect
,
6054 root_render_pass
->quad_list
.front()->visible_rect
);
6056 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
6057 gfx::RectF
expected_root_visible_rect(root
->bounds());
6058 EXPECT_EQ(expected_root_visible_rect
,
6059 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
6062 host_impl_
->DrawLayers(&frame
);
6063 host_impl_
->DidDrawAllLayers(frame
);
6064 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
6068 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
6069 scoped_ptr
<SolidColorLayerImpl
> root
=
6070 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6071 root
->SetPosition(gfx::PointF());
6072 root
->SetBounds(gfx::Size(10, 10));
6073 root
->SetDrawsContent(true);
6074 root
->SetHasRenderSurface(true);
6076 // Child layer is in the bottom right corner.
6077 scoped_ptr
<SolidColorLayerImpl
> child
=
6078 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
6079 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
6080 child
->SetBounds(gfx::Size(1, 1));
6081 child
->SetDrawsContent(true);
6082 root
->AddChild(child
.Pass());
6084 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6086 // Draw a frame. In the first frame, the entire viewport should be damaged.
6087 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6088 DrawFrameAndTestDamage(full_frame_damage
);
6090 // The second frame has damage that doesn't touch the child layer. Its quads
6091 // should still be generated.
6092 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
6093 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
6094 DrawFrameAndTestDamage(small_damage
);
6096 // The third frame should have no damage, so no quads should be generated.
6097 gfx::Rect no_damage
;
6098 DrawFrameAndTestDamage(no_damage
);
6101 // TODO(reveman): Remove this test and the ability to prevent on demand raster
6102 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
6103 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
6104 LayerTreeSettings settings
;
6105 CreateHostImpl(settings
, CreateOutputSurface());
6106 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
6109 class FakeMaskLayerImpl
: public LayerImpl
{
6111 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
6113 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
6116 void GetContentsResourceId(ResourceId
* resource_id
,
6117 gfx::Size
* resource_size
) const override
{
6122 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
6123 : LayerImpl(tree_impl
, id
) {}
6126 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
6128 using GLRenderer::ShouldAntialiasQuad
;
6131 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
6132 // Due to precision issues (especially on Android), sometimes far
6133 // away quads can end up thinking they need AA.
6134 float device_scale_factor
= 4.f
/ 3.f
;
6135 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
6136 gfx::Size
root_size(2000, 1000);
6137 gfx::Size device_viewport_size
=
6138 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
6139 host_impl_
->SetViewportSize(device_viewport_size
);
6141 host_impl_
->CreatePendingTree();
6142 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
6145 scoped_ptr
<LayerImpl
> scoped_root
=
6146 LayerImpl::Create(host_impl_
->pending_tree(), 1);
6147 LayerImpl
* root
= scoped_root
.get();
6148 root
->SetHasRenderSurface(true);
6150 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
6152 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
6153 LayerImpl::Create(host_impl_
->pending_tree(), 2);
6154 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
6155 root
->AddChild(scoped_scrolling_layer
.Pass());
6157 gfx::Size
content_layer_bounds(100000, 100);
6158 gfx::Size
pile_tile_size(3000, 3000);
6159 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
6160 pile_tile_size
, content_layer_bounds
));
6162 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
6163 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
6165 LayerImpl
* content_layer
= scoped_content_layer
.get();
6166 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
6167 content_layer
->SetBounds(content_layer_bounds
);
6168 content_layer
->SetDrawsContent(true);
6170 root
->SetBounds(root_size
);
6172 gfx::ScrollOffset
scroll_offset(100000, 0);
6173 scrolling_layer
->SetScrollClipLayer(root
->id());
6174 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
6176 host_impl_
->ActivateSyncTree();
6178 bool update_lcd_text
= false;
6179 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
6180 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
6182 LayerTreeHostImpl::FrameData frame
;
6183 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6185 ASSERT_EQ(1u, frame
.render_passes
.size());
6186 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
6187 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
6189 bool clipped
= false, force_aa
= false;
6190 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
6191 quad
->shared_quad_state
->quad_to_target_transform
,
6192 gfx::QuadF(quad
->shared_quad_state
->visible_quad_layer_rect
), &clipped
);
6193 EXPECT_FALSE(clipped
);
6195 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6196 device_layer_quad
, clipped
, force_aa
);
6197 EXPECT_FALSE(antialiased
);
6199 host_impl_
->DrawLayers(&frame
);
6200 host_impl_
->DidDrawAllLayers(frame
);
6204 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
6206 CompositorFrameMetadataTest()
6207 : swap_buffers_complete_(0) {}
6209 void DidSwapBuffersCompleteOnImplThread() override
{
6210 swap_buffers_complete_
++;
6213 int swap_buffers_complete_
;
6216 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
6217 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
6219 LayerTreeHostImpl::FrameData frame
;
6220 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6221 host_impl_
->DrawLayers(&frame
);
6222 host_impl_
->DidDrawAllLayers(frame
);
6224 CompositorFrameAck ack
;
6225 host_impl_
->ReclaimResources(&ack
);
6226 host_impl_
->DidSwapBuffersComplete();
6227 EXPECT_EQ(swap_buffers_complete_
, 1);
6230 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
6232 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6234 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
6236 return SoftwareOutputDevice::BeginPaint(damage_rect
);
6238 void EndPaint() override
{
6239 SoftwareOutputDevice::EndPaint();
6243 int frames_began_
, frames_ended_
;
6246 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
6247 // No main thread evictions in resourceless software mode.
6248 set_reduce_memory_result(false);
6249 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
6250 EXPECT_TRUE(CreateHostImpl(
6252 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
6253 host_impl_
->SetViewportSize(gfx::Size(50, 50));
6255 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6257 const gfx::Transform external_transform
;
6258 const gfx::Rect external_viewport
;
6259 const gfx::Rect external_clip
;
6260 const bool resourceless_software_draw
= true;
6261 host_impl_
->SetExternalDrawConstraints(external_transform
,
6266 resourceless_software_draw
);
6268 EXPECT_EQ(0, software_device
->frames_began_
);
6269 EXPECT_EQ(0, software_device
->frames_ended_
);
6273 EXPECT_EQ(1, software_device
->frames_began_
);
6274 EXPECT_EQ(1, software_device
->frames_ended_
);
6276 // Call another API method that is likely to hit nullptr in this mode.
6277 scoped_refptr
<base::trace_event::TracedValue
> state
=
6278 make_scoped_refptr(new base::trace_event::TracedValue());
6279 host_impl_
->ActivationStateAsValueInto(state
.get());
6282 TEST_F(LayerTreeHostImplTest
,
6283 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
6284 set_reduce_memory_result(false);
6285 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6286 FakeOutputSurface::CreateSoftware(
6287 make_scoped_ptr(new CountingSoftwareDevice
))));
6289 const gfx::Transform external_transform
;
6290 const gfx::Rect external_viewport
;
6291 const gfx::Rect external_clip
;
6292 const bool resourceless_software_draw
= true;
6293 host_impl_
->SetExternalDrawConstraints(external_transform
,
6298 resourceless_software_draw
);
6300 // SolidColorLayerImpl will be drawn.
6301 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
6302 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6304 // VideoLayerImpl will not be drawn.
6305 FakeVideoFrameProvider provider
;
6306 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6307 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
6308 video_layer
->SetBounds(gfx::Size(10, 10));
6309 video_layer
->SetDrawsContent(true);
6310 root_layer
->AddChild(video_layer
.Pass());
6311 SetupRootLayerImpl(root_layer
.Pass());
6313 LayerTreeHostImpl::FrameData frame
;
6314 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6315 host_impl_
->DrawLayers(&frame
);
6316 host_impl_
->DidDrawAllLayers(frame
);
6318 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
6319 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
6322 // Checks that we have a non-0 default allocation if we pass a context that
6323 // doesn't support memory management extensions.
6324 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
6325 LayerTreeSettings settings
;
6326 host_impl_
= LayerTreeHostImpl::Create(
6327 settings
, this, &proxy_
, &stats_instrumentation_
, &shared_bitmap_manager_
,
6328 &gpu_memory_buffer_manager_
, &task_graph_runner_
, 0);
6330 scoped_ptr
<OutputSurface
> output_surface(
6331 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6332 host_impl_
->InitializeRenderer(output_surface
.Pass());
6333 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
6336 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6337 ASSERT_TRUE(host_impl_
->active_tree());
6339 // RequiresHighResToDraw is set when new output surface is used.
6340 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6342 host_impl_
->ResetRequiresHighResToDraw();
6344 host_impl_
->SetVisible(false);
6345 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6346 host_impl_
->SetVisible(true);
6347 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6348 host_impl_
->SetVisible(false);
6349 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6351 host_impl_
->ResetRequiresHighResToDraw();
6353 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6354 host_impl_
->SetVisible(true);
6355 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6358 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6359 ASSERT_TRUE(host_impl_
->active_tree());
6360 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6362 // RequiresHighResToDraw is set when new output surface is used.
6363 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6365 host_impl_
->ResetRequiresHighResToDraw();
6367 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6368 host_impl_
->SetHasGpuRasterizationTrigger(false);
6369 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6370 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6371 host_impl_
->SetHasGpuRasterizationTrigger(true);
6372 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6373 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6374 host_impl_
->SetHasGpuRasterizationTrigger(false);
6375 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6376 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6378 host_impl_
->ResetRequiresHighResToDraw();
6380 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6381 host_impl_
->SetHasGpuRasterizationTrigger(true);
6382 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6383 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6386 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6388 void SetUp() override
{
6390 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_
,
6391 &shared_bitmap_manager_
, &task_graph_runner_
);
6392 host_impl_
.reset(fake_host_impl_
);
6393 host_impl_
->InitializeRenderer(CreateOutputSurface());
6394 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6397 FakeLayerTreeHostImpl
* fake_host_impl_
;
6400 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6401 fake_host_impl_
->DidModifyTilePriorities();
6402 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6403 fake_host_impl_
->SetVisible(false);
6404 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6407 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6408 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6409 TestWebGraphicsContext3D::Create();
6410 TestWebGraphicsContext3D
* context3d
= context
.get();
6411 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6412 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6414 EXPECT_EQ(0u, context3d
->NumTextures());
6416 UIResourceId ui_resource_id
= 1;
6417 bool is_opaque
= false;
6418 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6419 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6420 EXPECT_EQ(1u, context3d
->NumTextures());
6421 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6424 // Multiple requests with the same id is allowed. The previous texture is
6426 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6427 EXPECT_EQ(1u, context3d
->NumTextures());
6428 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6430 EXPECT_NE(id1
, id2
);
6432 // Deleting invalid UIResourceId is allowed and does not change state.
6433 host_impl_
->DeleteUIResource(-1);
6434 EXPECT_EQ(1u, context3d
->NumTextures());
6436 // Should return zero for invalid UIResourceId. Number of textures should
6438 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6439 EXPECT_EQ(1u, context3d
->NumTextures());
6441 host_impl_
->DeleteUIResource(ui_resource_id
);
6442 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6443 EXPECT_EQ(0u, context3d
->NumTextures());
6445 // Should not change state for multiple deletion on one UIResourceId
6446 host_impl_
->DeleteUIResource(ui_resource_id
);
6447 EXPECT_EQ(0u, context3d
->NumTextures());
6450 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6451 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6452 TestWebGraphicsContext3D::Create();
6453 TestWebGraphicsContext3D
* context3d
= context
.get();
6454 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6456 EXPECT_EQ(0u, context3d
->NumTextures());
6458 gfx::Size
size(4, 4);
6459 // SkImageInfo has no support for ETC1. The |info| below contains the right
6460 // total pixel size for the bitmap but not the right height and width. The
6461 // correct width/height are passed directly to UIResourceBitmap.
6463 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6464 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6465 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6466 pixel_ref
->setImmutable();
6467 UIResourceBitmap
bitmap(pixel_ref
, size
);
6468 UIResourceId ui_resource_id
= 1;
6469 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6470 EXPECT_EQ(1u, context3d
->NumTextures());
6471 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6475 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6478 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6479 scoped_refptr
<TestContextProvider
> context_provider
=
6480 TestContextProvider::Create();
6482 CreateHostImpl(DefaultSettings(),
6483 FakeOutputSurface::Create3d(context_provider
));
6485 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6487 ScopedPtrVector
<CopyOutputRequest
> requests
;
6488 requests
.push_back(CopyOutputRequest::CreateRequest(
6489 base::Bind(&ShutdownReleasesContext_Callback
)));
6491 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6493 LayerTreeHostImpl::FrameData frame
;
6494 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6495 host_impl_
->DrawLayers(&frame
);
6496 host_impl_
->DidDrawAllLayers(frame
);
6498 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6499 // texture in a texture mailbox.
6500 EXPECT_FALSE(context_provider
->HasOneRef());
6501 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6503 host_impl_
= nullptr;
6505 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6506 // released, and the texture deleted.
6507 EXPECT_TRUE(context_provider
->HasOneRef());
6508 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6511 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6512 // When flinging via touch, only the child should scroll (we should not
6514 gfx::Size
surface_size(10, 10);
6515 gfx::Size
content_size(20, 20);
6516 scoped_ptr
<LayerImpl
> root_clip
=
6517 LayerImpl::Create(host_impl_
->active_tree(), 3);
6518 root_clip
->SetHasRenderSurface(true);
6520 scoped_ptr
<LayerImpl
> root
=
6521 CreateScrollableLayer(1, content_size
, root_clip
.get());
6522 root
->SetIsContainerForFixedPositionLayers(true);
6523 scoped_ptr
<LayerImpl
> child
=
6524 CreateScrollableLayer(2, content_size
, root_clip
.get());
6526 root
->AddChild(child
.Pass());
6527 int root_id
= root
->id();
6528 root_clip
->AddChild(root
.Pass());
6530 host_impl_
->SetViewportSize(surface_size
);
6531 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6532 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6534 host_impl_
->active_tree()->DidBecomeActive();
6537 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6538 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6540 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6542 gfx::Vector2d
scroll_delta(0, 100);
6543 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6544 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6546 host_impl_
->ScrollEnd();
6548 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6549 host_impl_
->ProcessScrollDeltas();
6551 // Only the child should have scrolled.
6552 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6553 ExpectNone(*scroll_info
.get(), root_id
);
6557 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6558 // Scroll a child layer beyond its maximum scroll range and make sure the
6559 // the scroll doesn't bubble up to the parent layer.
6560 gfx::Size
surface_size(10, 10);
6561 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6562 root
->SetHasRenderSurface(true);
6563 scoped_ptr
<LayerImpl
> root_scrolling
=
6564 CreateScrollableLayer(2, surface_size
, root
.get());
6566 scoped_ptr
<LayerImpl
> grand_child
=
6567 CreateScrollableLayer(4, surface_size
, root
.get());
6568 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6570 scoped_ptr
<LayerImpl
> child
=
6571 CreateScrollableLayer(3, surface_size
, root
.get());
6572 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6573 child
->AddChild(grand_child
.Pass());
6575 root_scrolling
->AddChild(child
.Pass());
6576 root
->AddChild(root_scrolling
.Pass());
6577 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6578 host_impl_
->active_tree()->DidBecomeActive();
6579 host_impl_
->SetViewportSize(surface_size
);
6582 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6584 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6585 LayerImpl
* grand_child
= child
->children()[0];
6587 gfx::Vector2d
scroll_delta(0, -2);
6588 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6589 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6590 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6592 // The grand child should have scrolled up to its limit.
6593 scroll_info
= host_impl_
->ProcessScrollDeltas();
6594 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6596 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6597 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6599 // The child should have received the bubbled delta, but the locked
6600 // scrolling layer should remain set as the grand child.
6601 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6602 scroll_info
= host_impl_
->ProcessScrollDeltas();
6603 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6605 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6606 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(), scroll_delta
));
6607 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6609 // The first |ScrollBy| after the fling should re-lock the scrolling
6610 // layer to the first layer that scrolled, which is the child.
6611 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6612 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6613 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6615 // The child should have scrolled up to its limit.
6616 scroll_info
= host_impl_
->ProcessScrollDeltas();
6617 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6619 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6620 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(),
6621 scroll_delta
+ scroll_delta
));
6623 // As the locked layer is at it's limit, no further scrolling can occur.
6624 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6625 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6626 host_impl_
->ScrollEnd();
6630 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6631 // When flinging via wheel, the root should eventually scroll (we should
6633 gfx::Size
surface_size(10, 10);
6634 gfx::Size
content_size(20, 20);
6635 scoped_ptr
<LayerImpl
> root_clip
=
6636 LayerImpl::Create(host_impl_
->active_tree(), 3);
6637 root_clip
->SetHasRenderSurface(true);
6638 scoped_ptr
<LayerImpl
> root_scroll
=
6639 CreateScrollableLayer(1, content_size
, root_clip
.get());
6640 int root_scroll_id
= root_scroll
->id();
6641 scoped_ptr
<LayerImpl
> child
=
6642 CreateScrollableLayer(2, content_size
, root_clip
.get());
6644 root_scroll
->AddChild(child
.Pass());
6645 root_clip
->AddChild(root_scroll
.Pass());
6647 host_impl_
->SetViewportSize(surface_size
);
6648 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6649 host_impl_
->active_tree()->DidBecomeActive();
6652 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6653 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6655 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6657 gfx::Vector2d
scroll_delta(0, 100);
6658 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6659 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6661 host_impl_
->ScrollEnd();
6663 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6664 host_impl_
->ProcessScrollDeltas();
6666 // The root should have scrolled.
6667 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6668 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll_id
,
6669 gfx::Vector2d(0, 10)));
6673 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6674 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6675 // we should return SCROLL_UNKNOWN.
6676 gfx::Size
content_size(100, 100);
6677 SetupScrollAndContentsLayers(content_size
);
6679 int scroll_layer_id
= 2;
6680 LayerImpl
* scroll_layer
=
6681 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6682 scroll_layer
->SetDrawsContent(true);
6684 int page_scale_layer_id
= 5;
6685 LayerImpl
* page_scale_layer
=
6686 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6688 int occluder_layer_id
= 6;
6689 scoped_ptr
<LayerImpl
> occluder_layer
=
6690 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6691 occluder_layer
->SetDrawsContent(true);
6692 occluder_layer
->SetBounds(content_size
);
6693 occluder_layer
->SetPosition(gfx::PointF());
6695 // The parent of the occluder is *above* the scroller.
6696 page_scale_layer
->AddChild(occluder_layer
.Pass());
6700 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6701 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6704 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6705 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6706 // is not the first scroller we encounter when walking up from the layer, we
6707 // should also return SCROLL_UNKNOWN.
6708 gfx::Size
content_size(100, 100);
6709 SetupScrollAndContentsLayers(content_size
);
6711 int scroll_layer_id
= 2;
6712 LayerImpl
* scroll_layer
=
6713 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6714 scroll_layer
->SetDrawsContent(true);
6716 int occluder_layer_id
= 6;
6717 scoped_ptr
<LayerImpl
> occluder_layer
=
6718 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6719 occluder_layer
->SetDrawsContent(true);
6720 occluder_layer
->SetBounds(content_size
);
6721 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6723 int child_scroll_clip_layer_id
= 7;
6724 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6725 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6727 int child_scroll_layer_id
= 8;
6728 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6729 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6731 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6733 child_scroll
->AddChild(occluder_layer
.Pass());
6734 scroll_layer
->AddChild(child_scroll
.Pass());
6738 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6739 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6742 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6743 gfx::Size
content_size(100, 100);
6744 SetupScrollAndContentsLayers(content_size
);
6746 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6748 int scroll_layer_id
= 2;
6749 LayerImpl
* scroll_layer
=
6750 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6752 int child_scroll_layer_id
= 7;
6753 scoped_ptr
<LayerImpl
> child_scroll
=
6754 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6755 child_scroll
->SetDrawsContent(false);
6757 scroll_layer
->AddChild(child_scroll
.Pass());
6761 // We should not have scrolled |child_scroll| even though we technically "hit"
6762 // it. The reason for this is that if the scrolling the scroll would not move
6763 // any layer that is a drawn RSLL member, then we can ignore the hit.
6765 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6766 // started scrolling the inner viewport.
6767 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6768 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6770 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6773 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6774 gfx::Size
content_size(100, 100);
6775 SetupScrollAndContentsLayers(content_size
);
6777 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6778 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6780 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6781 CreateScrollableLayer(7, content_size
, root
);
6782 invisible_scroll_layer
->SetDrawsContent(false);
6784 scoped_ptr
<LayerImpl
> child_layer
=
6785 LayerImpl::Create(host_impl_
->active_tree(), 8);
6786 child_layer
->SetDrawsContent(false);
6788 scoped_ptr
<LayerImpl
> grand_child_layer
=
6789 LayerImpl::Create(host_impl_
->active_tree(), 9);
6790 grand_child_layer
->SetDrawsContent(true);
6791 grand_child_layer
->SetBounds(content_size
);
6792 // Move the grand child so it's not hit by our test point.
6793 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6795 child_layer
->AddChild(grand_child_layer
.Pass());
6796 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6797 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6801 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6802 // a descendant which is a drawn RSLL member.
6803 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6804 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6806 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6809 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6810 // This test case is very similar to the one above with one key difference:
6811 // the invisible scroller has a scroll child that is indeed draw contents.
6812 // If we attempt to initiate a gesture scroll off of the visible scroll child
6813 // we should still start the scroll child.
6814 gfx::Size
content_size(100, 100);
6815 SetupScrollAndContentsLayers(content_size
);
6817 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6819 int scroll_layer_id
= 2;
6820 LayerImpl
* scroll_layer
=
6821 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6823 int scroll_child_id
= 6;
6824 scoped_ptr
<LayerImpl
> scroll_child
=
6825 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6826 scroll_child
->SetDrawsContent(true);
6827 scroll_child
->SetBounds(content_size
);
6828 // Move the scroll child so it's not hit by our test point.
6829 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6831 int invisible_scroll_layer_id
= 7;
6832 scoped_ptr
<LayerImpl
> invisible_scroll
=
6833 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6834 invisible_scroll
->SetDrawsContent(false);
6836 int container_id
= 8;
6837 scoped_ptr
<LayerImpl
> container
=
6838 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6840 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6841 scroll_children
->insert(scroll_child
.get());
6842 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6844 scroll_child
->SetScrollParent(invisible_scroll
.get());
6846 container
->AddChild(invisible_scroll
.Pass());
6847 container
->AddChild(scroll_child
.Pass());
6849 scroll_layer
->AddChild(container
.Pass());
6853 // We should have scrolled |child_scroll| even though it is invisible.
6854 // The reason for this is that if the scrolling the scroll would move a layer
6855 // that is a drawn RSLL member, then we should accept this hit.
6856 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6857 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6859 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6862 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6863 // to CompositorFrameMetadata after SwapBuffers();
6864 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6865 scoped_ptr
<SolidColorLayerImpl
> root
=
6866 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6867 root
->SetPosition(gfx::PointF());
6868 root
->SetBounds(gfx::Size(10, 10));
6869 root
->SetDrawsContent(true);
6870 root
->SetHasRenderSurface(true);
6872 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6874 FakeOutputSurface
* fake_output_surface
=
6875 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6877 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6878 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6879 EXPECT_TRUE(metadata_latency_before
.empty());
6881 ui::LatencyInfo latency_info
;
6882 latency_info
.AddLatencyNumber(
6883 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6884 scoped_ptr
<SwapPromise
> swap_promise(
6885 new LatencyInfoSwapPromise(latency_info
));
6886 host_impl_
->active_tree()->QueueSwapPromise(swap_promise
.Pass());
6887 host_impl_
->SetNeedsRedraw();
6889 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6890 LayerTreeHostImpl::FrameData frame
;
6891 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6892 host_impl_
->DrawLayers(&frame
);
6893 host_impl_
->DidDrawAllLayers(frame
);
6894 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6896 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6897 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6898 EXPECT_EQ(1u, metadata_latency_after
.size());
6899 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6900 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6903 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6904 int root_layer_id
= 1;
6905 scoped_ptr
<SolidColorLayerImpl
> root
=
6906 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6907 root
->SetPosition(gfx::PointF());
6908 root
->SetBounds(gfx::Size(10, 10));
6909 root
->SetDrawsContent(true);
6910 root
->SetHasRenderSurface(true);
6912 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6914 // Ensure the default frame selection bounds are empty.
6915 FakeOutputSurface
* fake_output_surface
=
6916 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6917 const ViewportSelection
& selection_before
=
6918 fake_output_surface
->last_sent_frame().metadata
.selection
;
6919 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
6920 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
6922 // Plumb the layer-local selection bounds.
6923 gfx::PointF
selection_top(5, 0);
6924 gfx::PointF
selection_bottom(5, 5);
6925 LayerSelection selection
;
6926 selection
.start
.type
= SELECTION_BOUND_CENTER
;
6927 selection
.start
.layer_id
= root_layer_id
;
6928 selection
.start
.edge_bottom
= selection_bottom
;
6929 selection
.start
.edge_top
= selection_top
;
6930 selection
.end
= selection
.start
;
6931 host_impl_
->active_tree()->RegisterSelection(selection
);
6933 // Trigger a draw-swap sequence.
6934 host_impl_
->SetNeedsRedraw();
6936 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6937 LayerTreeHostImpl::FrameData frame
;
6938 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6939 host_impl_
->DrawLayers(&frame
);
6940 host_impl_
->DidDrawAllLayers(frame
);
6941 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6943 // Ensure the selection bounds have propagated to the frame metadata.
6944 const ViewportSelection
& selection_after
=
6945 fake_output_surface
->last_sent_frame().metadata
.selection
;
6946 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
6947 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
6948 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
6949 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
6950 EXPECT_TRUE(selection_after
.start
.visible
);
6951 EXPECT_TRUE(selection_after
.start
.visible
);
6954 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
6956 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
6957 LayerTreeHostImpl
* layer_tree_host_impl
,
6958 int* set_needs_commit_count
,
6959 int* set_needs_redraw_count
,
6960 int* forward_to_main_count
)
6961 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
6962 set_needs_commit_count_(set_needs_commit_count
),
6963 set_needs_redraw_count_(set_needs_redraw_count
),
6964 forward_to_main_count_(forward_to_main_count
) {}
6966 ~SimpleSwapPromiseMonitor() override
{}
6968 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
6970 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
6972 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
6973 (*forward_to_main_count_
)++;
6977 int* set_needs_commit_count_
;
6978 int* set_needs_redraw_count_
;
6979 int* forward_to_main_count_
;
6982 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
6983 int set_needs_commit_count
= 0;
6984 int set_needs_redraw_count
= 0;
6985 int forward_to_main_count
= 0;
6988 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6989 new SimpleSwapPromiseMonitor(NULL
,
6991 &set_needs_commit_count
,
6992 &set_needs_redraw_count
,
6993 &forward_to_main_count
));
6994 host_impl_
->SetNeedsRedraw();
6995 EXPECT_EQ(0, set_needs_commit_count
);
6996 EXPECT_EQ(1, set_needs_redraw_count
);
6997 EXPECT_EQ(0, forward_to_main_count
);
7000 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7002 host_impl_
->SetNeedsRedraw();
7003 EXPECT_EQ(0, set_needs_commit_count
);
7004 EXPECT_EQ(1, set_needs_redraw_count
);
7005 EXPECT_EQ(0, forward_to_main_count
);
7008 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7009 new SimpleSwapPromiseMonitor(NULL
,
7011 &set_needs_commit_count
,
7012 &set_needs_redraw_count
,
7013 &forward_to_main_count
));
7014 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
7015 EXPECT_EQ(0, set_needs_commit_count
);
7016 EXPECT_EQ(2, set_needs_redraw_count
);
7017 EXPECT_EQ(0, forward_to_main_count
);
7021 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7022 new SimpleSwapPromiseMonitor(NULL
,
7024 &set_needs_commit_count
,
7025 &set_needs_redraw_count
,
7026 &forward_to_main_count
));
7027 // Empty damage rect won't signal the monitor.
7028 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
7029 EXPECT_EQ(0, set_needs_commit_count
);
7030 EXPECT_EQ(2, set_needs_redraw_count
);
7031 EXPECT_EQ(0, forward_to_main_count
);
7035 set_needs_commit_count
= 0;
7036 set_needs_redraw_count
= 0;
7037 forward_to_main_count
= 0;
7038 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7039 new SimpleSwapPromiseMonitor(NULL
,
7041 &set_needs_commit_count
,
7042 &set_needs_redraw_count
,
7043 &forward_to_main_count
));
7044 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7046 // Scrolling normally should not trigger any forwarding.
7047 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7048 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7050 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7051 host_impl_
->ScrollEnd();
7053 EXPECT_EQ(0, set_needs_commit_count
);
7054 EXPECT_EQ(1, set_needs_redraw_count
);
7055 EXPECT_EQ(0, forward_to_main_count
);
7057 // Scrolling with a scroll handler should defer the swap to the main
7059 scroll_layer
->SetHaveScrollEventHandlers(true);
7060 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7061 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7063 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7064 host_impl_
->ScrollEnd();
7066 EXPECT_EQ(0, set_needs_commit_count
);
7067 EXPECT_EQ(2, set_needs_redraw_count
);
7068 EXPECT_EQ(1, forward_to_main_count
);
7072 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
7074 void SetUp() override
{
7075 LayerTreeSettings settings
= DefaultSettings();
7076 CreateHostImpl(settings
, CreateOutputSurface());
7077 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
7078 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
7079 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
7083 static const int top_controls_height_
;
7086 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
7088 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
7089 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7090 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7091 BeginFrameArgs begin_frame_args
=
7092 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7093 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7094 host_impl_
->Animate();
7095 EXPECT_FALSE(did_request_redraw_
);
7096 host_impl_
->DidFinishImplFrame();
7099 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
7100 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7101 EXPECT_FALSE(did_request_redraw_
);
7102 host_impl_
->CreatePendingTree();
7103 host_impl_
->sync_tree()->set_top_controls_height(100);
7104 host_impl_
->ActivateSyncTree();
7105 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
7108 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7109 TopControlsStayFullyVisibleOnHeightChange
) {
7110 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7111 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7113 host_impl_
->CreatePendingTree();
7114 host_impl_
->sync_tree()->set_top_controls_height(0);
7115 host_impl_
->ActivateSyncTree();
7116 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7118 host_impl_
->CreatePendingTree();
7119 host_impl_
->sync_tree()->set_top_controls_height(50);
7120 host_impl_
->ActivateSyncTree();
7121 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7124 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
7125 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7126 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7127 host_impl_
->DidChangeTopControlsPosition();
7128 EXPECT_TRUE(did_request_animate_
);
7129 EXPECT_TRUE(did_request_redraw_
);
7132 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
7133 InputHandlerScrollResult result
;
7134 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7135 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7136 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7137 BOTH
, SHOWN
, false);
7140 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7141 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7142 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7143 EXPECT_EQ(gfx::Vector2dF().ToString(),
7144 scroll_layer
->CurrentScrollOffset().ToString());
7146 // Scroll just the top controls and verify that the scroll succeeds.
7147 const float residue
= 10;
7148 float offset
= top_controls_height_
- residue
;
7149 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7150 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7151 EXPECT_TRUE(result
.did_scroll
);
7152 EXPECT_FLOAT_EQ(-offset
,
7153 host_impl_
->top_controls_manager()->ControlsTopOffset());
7154 EXPECT_EQ(gfx::Vector2dF().ToString(),
7155 scroll_layer
->CurrentScrollOffset().ToString());
7157 // Scroll across the boundary
7158 const float content_scroll
= 20;
7159 offset
= residue
+ content_scroll
;
7160 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7161 EXPECT_TRUE(result
.did_scroll
);
7162 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7163 EXPECT_EQ(-top_controls_height_
,
7164 host_impl_
->top_controls_manager()->ControlsTopOffset());
7165 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
7166 scroll_layer
->CurrentScrollOffset().ToString());
7168 // Now scroll back to the top of the content
7169 offset
= -content_scroll
;
7170 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7171 EXPECT_TRUE(result
.did_scroll
);
7172 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7173 EXPECT_EQ(-top_controls_height_
,
7174 host_impl_
->top_controls_manager()->ControlsTopOffset());
7175 EXPECT_EQ(gfx::Vector2dF().ToString(),
7176 scroll_layer
->CurrentScrollOffset().ToString());
7178 // And scroll the top controls completely into view
7179 offset
= -top_controls_height_
;
7180 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7181 EXPECT_TRUE(result
.did_scroll
);
7182 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7183 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7184 EXPECT_EQ(gfx::Vector2dF().ToString(),
7185 scroll_layer
->CurrentScrollOffset().ToString());
7187 // And attempt to scroll past the end
7188 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7189 EXPECT_FALSE(result
.did_scroll
);
7190 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, -50));
7191 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7192 EXPECT_EQ(gfx::Vector2dF().ToString(),
7193 scroll_layer
->CurrentScrollOffset().ToString());
7195 host_impl_
->ScrollEnd();
7198 TEST_F(LayerTreeHostImplWithTopControlsTest
, WheelUnhandledByTopControls
) {
7199 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7200 host_impl_
->SetViewportSize(gfx::Size(50, 100));
7201 host_impl_
->active_tree()->set_top_controls_shrink_blink_size(true);
7202 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7206 LayerImpl
* viewport_layer
= host_impl_
->InnerViewportScrollLayer();
7208 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7209 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7210 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7211 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer
->CurrentScrollOffset());
7213 // Wheel scrolls should not affect the top controls, and should pass
7214 // directly through to the viewport.
7215 const float delta
= top_controls_height_
;
7217 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7218 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7219 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
),
7220 viewport_layer
->CurrentScrollOffset());
7223 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7224 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7225 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
* 2),
7226 viewport_layer
->CurrentScrollOffset());
7229 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
7230 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7231 host_impl_
->SetViewportSize(gfx::Size(100, 200));
7232 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7233 BOTH
, SHOWN
, false);
7236 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7237 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7238 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7239 EXPECT_EQ(gfx::Vector2dF().ToString(),
7240 scroll_layer
->CurrentScrollOffset().ToString());
7242 // Scroll the top controls partially.
7243 const float residue
= 35;
7244 float offset
= top_controls_height_
- residue
;
7246 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7247 EXPECT_FLOAT_EQ(-offset
,
7248 host_impl_
->top_controls_manager()->ControlsTopOffset());
7249 EXPECT_EQ(gfx::Vector2dF().ToString(),
7250 scroll_layer
->CurrentScrollOffset().ToString());
7252 did_request_redraw_
= false;
7253 did_request_animate_
= false;
7254 did_request_commit_
= false;
7256 // End the scroll while the controls are still offset from their limit.
7257 host_impl_
->ScrollEnd();
7258 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7259 EXPECT_TRUE(did_request_animate_
);
7260 EXPECT_TRUE(did_request_redraw_
);
7261 EXPECT_FALSE(did_request_commit_
);
7263 // The top controls should properly animate until finished, despite the scroll
7264 // offset being at the origin.
7265 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7266 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7267 while (did_request_animate_
) {
7268 did_request_redraw_
= false;
7269 did_request_animate_
= false;
7270 did_request_commit_
= false;
7273 host_impl_
->top_controls_manager()->ControlsTopOffset();
7275 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7276 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7277 host_impl_
->Animate();
7278 EXPECT_EQ(gfx::Vector2dF().ToString(),
7279 scroll_layer
->CurrentScrollOffset().ToString());
7282 host_impl_
->top_controls_manager()->ControlsTopOffset();
7284 // No commit is needed as the controls are animating the content offset,
7285 // not the scroll offset.
7286 EXPECT_FALSE(did_request_commit_
);
7288 if (new_offset
!= old_offset
)
7289 EXPECT_TRUE(did_request_redraw_
);
7291 if (new_offset
!= 0) {
7292 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
7293 EXPECT_TRUE(did_request_animate_
);
7295 host_impl_
->DidFinishImplFrame();
7297 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7300 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
7301 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7302 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7303 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7304 BOTH
, SHOWN
, false);
7305 float initial_scroll_offset
= 50;
7306 scroll_layer
->PushScrollOffsetFromMainThread(
7307 gfx::ScrollOffset(0, initial_scroll_offset
));
7310 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7311 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7312 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7313 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7314 scroll_layer
->CurrentScrollOffset().ToString());
7316 // Scroll the top controls partially.
7317 const float residue
= 15;
7318 float offset
= top_controls_height_
- residue
;
7320 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7321 EXPECT_FLOAT_EQ(-offset
,
7322 host_impl_
->top_controls_manager()->ControlsTopOffset());
7323 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7324 scroll_layer
->CurrentScrollOffset().ToString());
7326 did_request_redraw_
= false;
7327 did_request_animate_
= false;
7328 did_request_commit_
= false;
7330 // End the scroll while the controls are still offset from the limit.
7331 host_impl_
->ScrollEnd();
7332 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7333 EXPECT_TRUE(did_request_animate_
);
7334 EXPECT_TRUE(did_request_redraw_
);
7335 EXPECT_FALSE(did_request_commit_
);
7337 // Animate the top controls to the limit.
7338 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7339 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7340 while (did_request_animate_
) {
7341 did_request_redraw_
= false;
7342 did_request_animate_
= false;
7343 did_request_commit_
= false;
7346 host_impl_
->top_controls_manager()->ControlsTopOffset();
7348 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7349 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7350 host_impl_
->Animate();
7353 host_impl_
->top_controls_manager()->ControlsTopOffset();
7355 if (new_offset
!= old_offset
) {
7356 EXPECT_TRUE(did_request_redraw_
);
7357 EXPECT_TRUE(did_request_commit_
);
7359 host_impl_
->DidFinishImplFrame();
7361 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7362 EXPECT_EQ(-top_controls_height_
,
7363 host_impl_
->top_controls_manager()->ControlsTopOffset());
7366 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7367 TopControlsAnimationAfterMainThreadFlingStopped
) {
7368 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7369 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7370 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7372 float initial_scroll_offset
= 50;
7373 scroll_layer
->PushScrollOffsetFromMainThread(
7374 gfx::ScrollOffset(0, initial_scroll_offset
));
7377 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7378 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7379 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7380 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7381 scroll_layer
->CurrentScrollOffset().ToString());
7383 // Scroll the top controls partially.
7384 const float residue
= 15;
7385 float offset
= top_controls_height_
- residue
;
7387 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7388 EXPECT_FLOAT_EQ(-offset
,
7389 host_impl_
->top_controls_manager()->ControlsTopOffset());
7390 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7391 scroll_layer
->CurrentScrollOffset().ToString());
7393 did_request_redraw_
= false;
7394 did_request_animate_
= false;
7395 did_request_commit_
= false;
7397 // End the fling while the controls are still offset from the limit.
7398 host_impl_
->MainThreadHasStoppedFlinging();
7399 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7400 EXPECT_TRUE(did_request_animate_
);
7401 EXPECT_TRUE(did_request_redraw_
);
7402 EXPECT_FALSE(did_request_commit_
);
7404 // Animate the top controls to the limit.
7405 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7406 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7407 while (did_request_animate_
) {
7408 did_request_redraw_
= false;
7409 did_request_animate_
= false;
7410 did_request_commit_
= false;
7412 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7414 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7415 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7416 host_impl_
->Animate();
7418 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7420 if (new_offset
!= old_offset
) {
7421 EXPECT_TRUE(did_request_redraw_
);
7422 EXPECT_TRUE(did_request_commit_
);
7424 host_impl_
->DidFinishImplFrame();
7426 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7427 EXPECT_EQ(-top_controls_height_
,
7428 host_impl_
->top_controls_manager()->ControlsTopOffset());
7431 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7432 TopControlsScrollDeltaInOverScroll
) {
7433 // Verifies that the overscroll delta should not have accumulated in
7434 // the top controls if we do a hide and show without releasing finger.
7436 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7437 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7438 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7442 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7443 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7444 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7448 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7449 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7450 EXPECT_EQ(gfx::Vector2dF().ToString(),
7451 scroll_layer
->CurrentScrollOffset().ToString());
7454 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7455 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7456 scroll_layer
->CurrentScrollOffset().ToString());
7459 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7461 // Should have fully scrolled
7462 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7463 scroll_layer
->CurrentScrollOffset().ToString());
7465 float overscrollamount
= 10;
7467 // Overscroll the content
7469 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7471 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7472 scroll_layer
->CurrentScrollOffset().ToString());
7473 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7474 host_impl_
->accumulated_root_overscroll().ToString());
7476 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7478 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7479 scroll_layer
->CurrentScrollOffset().ToString());
7480 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7483 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7484 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7485 scroll_layer
->CurrentScrollOffset().ToString());
7487 // Top controls should be fully visible
7488 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7490 host_impl_
->ScrollEnd();
7493 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7495 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7496 const gfx::Size
& outer_viewport
,
7497 const gfx::Size
& inner_viewport
) {
7498 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7499 const int kOuterViewportClipLayerId
= 6;
7500 const int kOuterViewportScrollLayerId
= 7;
7501 const int kInnerViewportScrollLayerId
= 2;
7502 const int kInnerViewportClipLayerId
= 4;
7503 const int kPageScaleLayerId
= 5;
7505 scoped_ptr
<LayerImpl
> inner_scroll
=
7506 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7507 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7508 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7510 scoped_ptr
<LayerImpl
> inner_clip
=
7511 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7512 inner_clip
->SetBounds(inner_viewport
);
7514 scoped_ptr
<LayerImpl
> page_scale
=
7515 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7517 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7518 inner_scroll
->SetBounds(outer_viewport
);
7519 inner_scroll
->SetPosition(gfx::PointF());
7521 scoped_ptr
<LayerImpl
> outer_clip
=
7522 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7523 outer_clip
->SetBounds(outer_viewport
);
7524 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7526 scoped_ptr
<LayerImpl
> outer_scroll
=
7527 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7528 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7529 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7530 outer_scroll
->SetBounds(content_size
);
7531 outer_scroll
->SetPosition(gfx::PointF());
7533 scoped_ptr
<LayerImpl
> contents
=
7534 LayerImpl::Create(layer_tree_impl
, 8);
7535 contents
->SetDrawsContent(true);
7536 contents
->SetBounds(content_size
);
7537 contents
->SetPosition(gfx::PointF());
7539 outer_scroll
->AddChild(contents
.Pass());
7540 outer_clip
->AddChild(outer_scroll
.Pass());
7541 inner_scroll
->AddChild(outer_clip
.Pass());
7542 page_scale
->AddChild(inner_scroll
.Pass());
7543 inner_clip
->AddChild(page_scale
.Pass());
7545 inner_clip
->SetHasRenderSurface(true);
7546 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7547 layer_tree_impl
->SetViewportLayersFromIds(
7548 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7549 kOuterViewportScrollLayerId
);
7551 host_impl_
->active_tree()->DidBecomeActive();
7555 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7556 gfx::Size content_size
= gfx::Size(100, 160);
7557 gfx::Size outer_viewport
= gfx::Size(50, 80);
7558 gfx::Size inner_viewport
= gfx::Size(25, 40);
7560 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7562 TestScrollOffsetDelegate scroll_delegate
;
7563 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7565 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7566 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7569 gfx::ScrollOffset inner_expected
;
7570 gfx::ScrollOffset outer_expected
;
7571 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7572 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7574 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7576 scroll_delegate
.set_getter_return_value(current_offset
);
7577 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
7578 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7579 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7581 // Outer viewport scrolls first. Then the rest is applied to the inner
7583 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7584 inner_scroll
->CurrentScrollOffset());
7585 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7586 outer_scroll
->CurrentScrollOffset());
7590 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7591 gfx::Size content_size
= gfx::Size(100, 160);
7592 gfx::Size outer_viewport
= gfx::Size(50, 80);
7593 gfx::Size inner_viewport
= gfx::Size(25, 40);
7595 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7597 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7598 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7601 gfx::Vector2dF inner_expected
;
7602 gfx::Vector2dF outer_expected
;
7603 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7604 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7606 // Make sure the fling goes to the outer viewport first
7607 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7608 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7609 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7610 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7611 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7613 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7614 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7615 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7616 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), outer_scroll
);
7618 host_impl_
->ScrollEnd();
7619 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7621 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7622 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7624 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7625 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7626 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7627 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7628 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7629 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7631 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7632 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7633 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7635 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7636 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7637 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7639 host_impl_
->ScrollEnd();
7640 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7642 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7643 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7647 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7648 DiagonalScrollBubblesPerfectlyToInner
) {
7649 gfx::Size content_size
= gfx::Size(100, 160);
7650 gfx::Size outer_viewport
= gfx::Size(50, 80);
7651 gfx::Size inner_viewport
= gfx::Size(25, 40);
7653 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7655 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7656 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7659 gfx::Vector2dF inner_expected
;
7660 gfx::Vector2dF outer_expected
;
7661 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7662 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7664 // Make sure the scroll goes to the outer viewport first.
7665 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7666 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7667 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7668 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7669 InputHandler::GESTURE
));
7671 // Scroll near the edge of the outer viewport.
7672 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7673 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7674 outer_expected
+= scroll_delta
;
7675 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7676 InputHandler::GESTURE
));
7678 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7679 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7681 // Now diagonal scroll across the outer viewport boundary in a single event.
7682 // The entirety of the scroll should be consumed, as bubbling between inner
7683 // and outer viewport layers is perfect.
7684 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7685 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7686 InputHandler::GESTURE
));
7687 outer_expected
+= scroll_delta
;
7688 inner_expected
+= scroll_delta
;
7689 host_impl_
->ScrollEnd();
7690 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7691 gfx::Point(), InputHandler::GESTURE
));
7693 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7694 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7698 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7699 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7700 gfx::Size content_size
= gfx::Size(100, 160);
7701 gfx::Size outer_viewport
= gfx::Size(50, 80);
7702 gfx::Size inner_viewport
= gfx::Size(25, 40);
7704 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7706 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7707 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7709 scoped_ptr
<LayerImpl
> child
=
7710 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7711 LayerImpl
* child_scroll
= child
.get();
7712 outer_scroll
->children()[0]->AddChild(child
.Pass());
7716 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7718 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7719 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7720 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7721 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7722 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7723 InputHandler::GESTURE
));
7725 // The child should have scrolled up to its limit.
7726 scroll_info
= host_impl_
->ProcessScrollDeltas();
7727 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7729 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7730 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7732 // The first |ScrollBy| after the fling should re-lock the scrolling
7733 // layer to the first layer that scrolled, the inner viewport scroll layer.
7734 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7735 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7736 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7737 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7738 InputHandler::GESTURE
));
7740 // The inner viewport should have scrolled up to its limit.
7741 scroll_info
= host_impl_
->ProcessScrollDeltas();
7742 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7744 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7746 ScrollInfoContains(*scroll_info
, inner_scroll
->id(), scroll_delta
));
7748 // As the locked layer is at its limit, no further scrolling can occur.
7749 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7750 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7751 host_impl_
->ScrollEnd();
7752 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7753 gfx::Point(), InputHandler::GESTURE
));
7757 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7758 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest
) {
7759 gfx::Size content_size
= gfx::Size(100, 160);
7760 gfx::Size outer_viewport
= gfx::Size(50, 80);
7761 gfx::Size inner_viewport
= gfx::Size(25, 40);
7763 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7765 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7766 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7768 scoped_ptr
<LayerImpl
> child
=
7769 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7770 LayerImpl
* child_scroll
= child
.get();
7771 outer_scroll
->children()[0]->AddChild(child
.Pass());
7775 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7776 host_impl_
->RootScrollBegin(InputHandler::GESTURE
));
7777 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7778 host_impl_
->ScrollEnd();
7779 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7780 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7781 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7782 host_impl_
->ScrollEnd();
7785 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7786 NoOverscrollWhenInnerViewportCantScroll
) {
7787 InputHandlerScrollResult scroll_result
;
7788 gfx::Size content_size
= gfx::Size(100, 160);
7789 gfx::Size outer_viewport
= gfx::Size(50, 80);
7790 gfx::Size inner_viewport
= gfx::Size(25, 40);
7791 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7794 // Make inner viewport unscrollable.
7795 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7796 inner_scroll
->set_user_scrollable_horizontal(false);
7797 inner_scroll
->set_user_scrollable_vertical(false);
7799 // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
7800 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7801 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7802 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7803 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
7804 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7806 // When inner viewport is unscrollable, a fling gives zero overscroll.
7807 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
7808 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
7811 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7813 void SetUp() override
{
7814 LayerTreeSettings settings
= DefaultSettings();
7815 settings
.max_memory_for_prepaint_percentage
= 50;
7816 CreateHostImpl(settings
, CreateOutputSurface());
7820 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7821 // Set up a memory policy and percentages which could cause
7822 // 32-bit integer overflows.
7823 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7825 // Verify implicit limits are calculated correctly with no overflows
7826 host_impl_
->SetMemoryPolicy(mem_policy
);
7827 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7828 300u * 1024u * 1024u);
7829 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7830 150u * 1024u * 1024u);
7833 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7834 const gfx::Size
layer_size(100, 100);
7835 gfx::Transform external_transform
;
7836 const gfx::Rect
external_viewport(layer_size
);
7837 const gfx::Rect
external_clip(layer_size
);
7838 const bool resourceless_software_draw
= false;
7839 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7841 host_impl_
->SetExternalDrawConstraints(external_transform
,
7846 resourceless_software_draw
);
7848 EXPECT_TRANSFORMATION_MATRIX_EQ(
7849 external_transform
, layer
->draw_properties().target_space_transform
);
7851 external_transform
.Translate(20, 20);
7852 host_impl_
->SetExternalDrawConstraints(external_transform
,
7857 resourceless_software_draw
);
7859 EXPECT_TRANSFORMATION_MATRIX_EQ(
7860 external_transform
, layer
->draw_properties().target_space_transform
);
7863 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7864 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7867 base::TimeTicks start_time
=
7868 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7870 BeginFrameArgs begin_frame_args
=
7871 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7873 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7874 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7876 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7878 begin_frame_args
.frame_time
= start_time
;
7879 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7880 host_impl_
->Animate();
7881 host_impl_
->UpdateAnimationState(true);
7883 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7884 host_impl_
->DidFinishImplFrame();
7886 begin_frame_args
.frame_time
=
7887 start_time
+ base::TimeDelta::FromMilliseconds(50);
7888 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7889 host_impl_
->Animate();
7890 host_impl_
->UpdateAnimationState(true);
7892 float y
= scrolling_layer
->CurrentScrollOffset().y();
7893 EXPECT_TRUE(y
> 1 && y
< 49);
7896 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7897 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7898 host_impl_
->DidFinishImplFrame();
7900 begin_frame_args
.frame_time
=
7901 start_time
+ base::TimeDelta::FromMilliseconds(200);
7902 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7903 host_impl_
->Animate();
7904 host_impl_
->UpdateAnimationState(true);
7906 y
= scrolling_layer
->CurrentScrollOffset().y();
7907 EXPECT_TRUE(y
> 50 && y
< 100);
7908 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7909 host_impl_
->DidFinishImplFrame();
7911 begin_frame_args
.frame_time
=
7912 start_time
+ base::TimeDelta::FromMilliseconds(250);
7913 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7914 host_impl_
->Animate();
7915 host_impl_
->UpdateAnimationState(true);
7917 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7918 scrolling_layer
->CurrentScrollOffset());
7919 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7920 host_impl_
->DidFinishImplFrame();
7923 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
7924 TEST_F(LayerTreeHostImplTimelinesTest
, ScrollAnimated
) {
7925 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7928 base::TimeTicks start_time
=
7929 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7931 BeginFrameArgs begin_frame_args
=
7932 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7934 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7935 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7937 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7939 begin_frame_args
.frame_time
= start_time
;
7940 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7941 host_impl_
->Animate();
7942 host_impl_
->UpdateAnimationState(true);
7944 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7945 host_impl_
->DidFinishImplFrame();
7947 begin_frame_args
.frame_time
=
7948 start_time
+ base::TimeDelta::FromMilliseconds(50);
7949 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7950 host_impl_
->Animate();
7951 host_impl_
->UpdateAnimationState(true);
7953 float y
= scrolling_layer
->CurrentScrollOffset().y();
7954 EXPECT_TRUE(y
> 1 && y
< 49);
7957 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7958 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7959 host_impl_
->DidFinishImplFrame();
7961 begin_frame_args
.frame_time
=
7962 start_time
+ base::TimeDelta::FromMilliseconds(200);
7963 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7964 host_impl_
->Animate();
7965 host_impl_
->UpdateAnimationState(true);
7967 y
= scrolling_layer
->CurrentScrollOffset().y();
7968 EXPECT_TRUE(y
> 50 && y
< 100);
7969 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7970 host_impl_
->DidFinishImplFrame();
7972 begin_frame_args
.frame_time
=
7973 start_time
+ base::TimeDelta::FromMilliseconds(250);
7974 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7975 host_impl_
->Animate();
7976 host_impl_
->UpdateAnimationState(true);
7978 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7979 scrolling_layer
->CurrentScrollOffset());
7980 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7981 host_impl_
->DidFinishImplFrame();
7984 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
7985 host_impl_
->CreatePendingTree();
7987 Region empty_invalidation
;
7988 scoped_refptr
<RasterSource
> pile_with_tiles(
7989 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7990 gfx::Size(10, 10)));
7992 scoped_ptr
<FakePictureLayerImpl
> layer
=
7993 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
7994 layer
->SetBounds(gfx::Size(10, 10));
7995 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
7996 layer
->SetDrawsContent(true);
7997 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
7998 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
7999 layer
->tilings()->tiling_at(0)->set_resolution(
8000 TileResolution::HIGH_RESOLUTION
);
8001 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
8002 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
8003 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
8004 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
8006 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
8007 host_impl_
->pending_tree()->root_layer());
8009 root_layer
->set_has_valid_tile_priorities(true);
8010 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
8011 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8012 RasterTilePriorityQueue::Type::ALL
);
8013 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
8015 root_layer
->set_has_valid_tile_priorities(false);
8016 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
8017 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8018 RasterTilePriorityQueue::Type::ALL
);
8019 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
8022 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
8023 host_impl_
->CreatePendingTree();
8024 host_impl_
->ActivateSyncTree();
8025 host_impl_
->CreatePendingTree();
8027 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
8029 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
8030 FakePictureLayerImpl::Create(pending_tree
, 10);
8031 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
8032 pending_tree
->SetRootLayer(pending_layer
.Pass());
8033 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
8035 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
8036 pending_tree
->DidBecomeActive();
8037 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8039 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
8040 FakePictureLayerImpl::Create(pending_tree
, 11);
8041 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
8042 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
8043 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
8045 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8046 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
8047 pending_tree
->DidBecomeActive();
8048 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8049 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8051 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
8052 FakePictureLayerImpl::Create(pending_tree
, 12);
8053 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
8054 FakePictureLayerImpl::Create(pending_tree
, 13);
8055 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
8056 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
8057 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
8058 ASSERT_EQ(raw_replica_mask_layer
,
8059 raw_pending_layer
->replica_layer()->mask_layer());
8061 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8062 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8063 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
8064 pending_tree
->DidBecomeActive();
8065 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
8066 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
8067 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
8070 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
8071 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
8072 host_impl_
->SetViewportSize(gfx::Size(50, 50));
8075 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
8077 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
8078 float page_scale_factor
= 1.f
;
8080 // The scroll deltas should have the page scale factor applied.
8082 host_impl_
->active_tree()->PushPageScaleFromMainThread(
8083 page_scale_factor
, min_page_scale
, max_page_scale
);
8084 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
8085 scroll_layer
->SetScrollDelta(gfx::Vector2d());
8087 float page_scale_delta
= 2.f
;
8088 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
8089 host_impl_
->PinchGestureBegin();
8090 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
8091 host_impl_
->PinchGestureEnd();
8092 host_impl_
->ScrollEnd();
8094 gfx::Vector2dF
scroll_delta(0, 5);
8095 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8096 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
8097 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
8099 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
8100 host_impl_
->ScrollEnd();
8101 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8102 scroll_layer
->CurrentScrollOffset());
8106 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
8108 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8109 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
8112 int num_lost_surfaces_
;
8115 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
8116 // Really we just need at least one client notification each time
8117 // we go from having a valid output surface to not having a valid output
8119 EXPECT_EQ(0, num_lost_surfaces_
);
8120 host_impl_
->DidLoseOutputSurface();
8121 EXPECT_EQ(1, num_lost_surfaces_
);
8122 host_impl_
->DidLoseOutputSurface();
8123 EXPECT_LE(1, num_lost_surfaces_
);
8126 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
8127 LayerTreeHostImpl::FrameData frame
;
8128 frame
.render_passes
.push_back(RenderPass::Create());
8129 RenderPass
* pass3
= frame
.render_passes
.back();
8130 frame
.render_passes
.push_back(RenderPass::Create());
8131 RenderPass
* pass2
= frame
.render_passes
.back();
8132 frame
.render_passes
.push_back(RenderPass::Create());
8133 RenderPass
* pass1
= frame
.render_passes
.back();
8135 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8136 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8137 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8139 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8140 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8141 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8143 // Add a quad to each pass so they aren't empty.
8144 SolidColorDrawQuad
* color_quad
;
8145 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8146 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8147 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8148 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8149 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8150 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8152 // pass3 is referenced by pass2.
8153 RenderPassDrawQuad
* rpdq
=
8154 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8155 rpdq
->material
= DrawQuad::RENDER_PASS
;
8156 rpdq
->render_pass_id
= pass3
->id
;
8158 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
8159 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8160 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8161 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8162 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8163 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8164 EXPECT_EQ(1u, frame
.render_passes
.size());
8165 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8168 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
8169 LayerTreeHostImpl::FrameData frame
;
8170 frame
.render_passes
.push_back(RenderPass::Create());
8171 RenderPass
* pass3
= frame
.render_passes
.back();
8172 frame
.render_passes
.push_back(RenderPass::Create());
8173 RenderPass
* pass2
= frame
.render_passes
.back();
8174 frame
.render_passes
.push_back(RenderPass::Create());
8175 RenderPass
* pass1
= frame
.render_passes
.back();
8177 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8178 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8179 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8181 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8182 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8183 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8185 // pass1 is not empty, but pass2 and pass3 are.
8186 SolidColorDrawQuad
* color_quad
;
8187 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8188 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8190 // pass3 is referenced by pass2.
8191 RenderPassDrawQuad
* rpdq
=
8192 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8193 rpdq
->material
= DrawQuad::RENDER_PASS
;
8194 rpdq
->render_pass_id
= pass3
->id
;
8196 // pass2 is referenced by pass1.
8197 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8198 rpdq
->material
= DrawQuad::RENDER_PASS
;
8199 rpdq
->render_pass_id
= pass2
->id
;
8201 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8202 // should be removed.
8203 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8204 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8205 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8206 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8207 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8208 EXPECT_EQ(1u, frame
.render_passes
.size());
8209 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8210 // The RenderPassDrawQuad should be removed from pass1.
8211 EXPECT_EQ(1u, pass1
->quad_list
.size());
8212 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
8215 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
8216 LayerTreeHostImpl::FrameData frame
;
8217 frame
.render_passes
.push_back(RenderPass::Create());
8218 RenderPass
* pass3
= frame
.render_passes
.back();
8219 frame
.render_passes
.push_back(RenderPass::Create());
8220 RenderPass
* pass2
= frame
.render_passes
.back();
8221 frame
.render_passes
.push_back(RenderPass::Create());
8222 RenderPass
* pass1
= frame
.render_passes
.back();
8224 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8225 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8226 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8228 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8229 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8230 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8232 // pass3 is referenced by pass2.
8233 RenderPassDrawQuad
* rpdq
=
8234 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8235 rpdq
->material
= DrawQuad::RENDER_PASS
;
8236 rpdq
->render_pass_id
= pass3
->id
;
8238 // pass2 is referenced by pass1.
8239 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8240 rpdq
->material
= DrawQuad::RENDER_PASS
;
8241 rpdq
->render_pass_id
= pass2
->id
;
8243 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8244 // should be removed. Then pass1 is empty too, but it's the root so it should
8246 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8247 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8248 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8249 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8250 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8251 EXPECT_EQ(1u, frame
.render_passes
.size());
8252 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8253 // The RenderPassDrawQuad should be removed from pass1.
8254 EXPECT_EQ(0u, pass1
->quad_list
.size());
8257 class FakeVideoFrameController
: public VideoFrameController
{
8259 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
8260 begin_frame_args_
= args
;
8261 did_draw_frame_
= false;
8264 void DidDrawFrame() override
{ did_draw_frame_
= true; }
8266 const BeginFrameArgs
& begin_frame_args() const { return begin_frame_args_
; }
8268 bool did_draw_frame() const { return did_draw_frame_
; }
8271 BeginFrameArgs begin_frame_args_
;
8272 bool did_draw_frame_
= false;
8275 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
8276 BeginFrameArgs begin_frame_args
=
8277 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8278 FakeVideoFrameController controller
;
8280 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8281 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8282 host_impl_
->AddVideoFrameController(&controller
);
8283 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8284 host_impl_
->DidFinishImplFrame();
8286 EXPECT_FALSE(controller
.did_draw_frame());
8287 LayerTreeHostImpl::FrameData frame
;
8288 host_impl_
->DidDrawAllLayers(frame
);
8289 EXPECT_TRUE(controller
.did_draw_frame());
8291 controller
.OnBeginFrame(begin_frame_args
);
8292 EXPECT_FALSE(controller
.did_draw_frame());
8293 host_impl_
->RemoveVideoFrameController(&controller
);
8294 host_impl_
->DidDrawAllLayers(frame
);
8295 EXPECT_FALSE(controller
.did_draw_frame());
8298 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
8299 BeginFrameArgs begin_frame_args
=
8300 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8301 FakeVideoFrameController controller
;
8303 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8304 host_impl_
->DidFinishImplFrame();
8306 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8307 host_impl_
->AddVideoFrameController(&controller
);
8308 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8310 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8311 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8312 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8313 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8315 EXPECT_FALSE(controller
.did_draw_frame());
8316 LayerTreeHostImpl::FrameData frame
;
8317 host_impl_
->DidDrawAllLayers(frame
);
8318 EXPECT_TRUE(controller
.did_draw_frame());
8320 controller
.OnBeginFrame(begin_frame_args
);
8321 EXPECT_FALSE(controller
.did_draw_frame());
8322 host_impl_
->RemoveVideoFrameController(&controller
);
8323 host_impl_
->DidDrawAllLayers(frame
);
8324 EXPECT_FALSE(controller
.did_draw_frame());
8327 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
8328 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8330 host_impl_
->SetHasGpuRasterizationTrigger(true);
8331 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8332 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
8333 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8335 host_impl_
->SetHasGpuRasterizationTrigger(false);
8336 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8337 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
8338 host_impl_
->gpu_rasterization_status());
8339 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8341 host_impl_
->SetHasGpuRasterizationTrigger(true);
8342 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8343 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
8344 host_impl_
->gpu_rasterization_status());
8345 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8346 EXPECT_FALSE(host_impl_
->use_msaa());
8348 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
8349 TestWebGraphicsContext3D::Create();
8350 context_with_msaa
->SetMaxSamples(8);
8352 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
8353 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
8354 EXPECT_TRUE(CreateHostImpl(
8355 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
8356 host_impl_
->SetHasGpuRasterizationTrigger(true);
8357 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8358 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
8359 host_impl_
->gpu_rasterization_status());
8360 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8361 EXPECT_TRUE(host_impl_
->use_msaa());
8363 LayerTreeSettings settings
= DefaultSettings();
8364 settings
.gpu_rasterization_enabled
= false;
8365 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8366 host_impl_
->SetHasGpuRasterizationTrigger(true);
8367 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8368 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
8369 host_impl_
->gpu_rasterization_status());
8370 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8372 settings
.gpu_rasterization_forced
= true;
8373 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8375 host_impl_
->SetHasGpuRasterizationTrigger(false);
8376 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8377 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
8378 host_impl_
->gpu_rasterization_status());
8379 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8382 // A mock output surface which lets us detect calls to ForceReclaimResources.
8383 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
8385 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
8386 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8387 TestContextProvider::Create(), TestContextProvider::Create(), false));
8390 MOCK_METHOD0(ForceReclaimResources
, void());
8393 MockReclaimResourcesOutputSurface(
8394 scoped_refptr
<ContextProvider
> context_provider
,
8395 scoped_refptr
<ContextProvider
> worker_context_provider
,
8396 bool delegated_rendering
)
8397 : FakeOutputSurface(context_provider
,
8398 worker_context_provider
,
8399 delegated_rendering
) {}
8402 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8403 // being reclaimed to block drawing between BeginCommit / Swap. This test
8404 // ensures that BeginCommit triggers ForceReclaimResources. See
8405 // crbug.com/489515.
8406 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
8407 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
8408 MockReclaimResourcesOutputSurface::Create3d());
8409 // Hold an unowned pointer to the output surface to use for mock expectations.
8410 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
8412 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
8413 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
8414 host_impl_
->BeginCommit();