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/render_pass_test_common.h"
57 #include "cc/test/test_gpu_memory_buffer_manager.h"
58 #include "cc/test/test_shared_bitmap_manager.h"
59 #include "cc/test/test_task_graph_runner.h"
60 #include "cc/test/test_web_graphics_context_3d.h"
61 #include "cc/trees/layer_tree_impl.h"
62 #include "cc/trees/single_thread_proxy.h"
63 #include "media/base/media.h"
64 #include "testing/gmock/include/gmock/gmock.h"
65 #include "testing/gtest/include/gtest/gtest.h"
66 #include "third_party/skia/include/core/SkMallocPixelRef.h"
67 #include "ui/gfx/geometry/rect_conversions.h"
68 #include "ui/gfx/geometry/size_conversions.h"
69 #include "ui/gfx/geometry/vector2d_conversions.h"
71 using ::testing::Mock
;
72 using ::testing::Return
;
73 using ::testing::AnyNumber
;
74 using ::testing::AtLeast
;
76 using media::VideoFrame
;
81 class LayerTreeHostImplTest
: public testing::Test
,
82 public LayerTreeHostImplClient
{
84 LayerTreeHostImplTest()
85 : proxy_(base::ThreadTaskRunnerHandle::Get(),
86 base::ThreadTaskRunnerHandle::Get()),
87 always_impl_thread_(&proxy_
),
88 always_main_thread_blocked_(&proxy_
),
89 on_can_draw_state_changed_called_(false),
90 did_notify_ready_to_activate_(false),
91 did_request_commit_(false),
92 did_request_redraw_(false),
93 did_request_animate_(false),
94 did_request_prepare_tiles_(false),
95 did_complete_page_scale_animation_(false),
96 reduce_memory_result_(true) {
97 media::InitializeMediaLibrary();
100 LayerTreeSettings
DefaultSettings() {
101 LayerTreeSettings settings
;
102 settings
.minimum_occlusion_tracking_size
= gfx::Size();
103 settings
.renderer_settings
.texture_id_allocation_chunk_size
= 1;
104 settings
.gpu_rasterization_enabled
= true;
108 void SetUp() override
{
109 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
112 void TearDown() override
{}
114 void UpdateRendererCapabilitiesOnImplThread() override
{}
115 void DidLoseOutputSurfaceOnImplThread() override
{}
116 void CommitVSyncParameters(base::TimeTicks timebase
,
117 base::TimeDelta interval
) override
{}
118 void SetEstimatedParentDrawTime(base::TimeDelta draw_time
) override
{}
119 void SetMaxSwapsPendingOnImplThread(int max
) override
{}
120 void DidSwapBuffersOnImplThread() override
{}
121 void DidSwapBuffersCompleteOnImplThread() override
{}
122 void OnCanDrawStateChanged(bool can_draw
) override
{
123 on_can_draw_state_changed_called_
= true;
125 void NotifyReadyToActivate() override
{
126 did_notify_ready_to_activate_
= true;
127 host_impl_
->ActivateSyncTree();
129 void NotifyReadyToDraw() override
{}
130 void SetNeedsRedrawOnImplThread() override
{ did_request_redraw_
= true; }
131 void SetNeedsRedrawRectOnImplThread(const gfx::Rect
& damage_rect
) override
{
132 did_request_redraw_
= true;
134 void SetNeedsAnimateOnImplThread() override
{ did_request_animate_
= true; }
135 void SetNeedsPrepareTilesOnImplThread() override
{
136 did_request_prepare_tiles_
= true;
138 void SetNeedsCommitOnImplThread() override
{ did_request_commit_
= true; }
139 void SetVideoNeedsBeginFrames(bool needs_begin_frames
) override
{}
140 void PostAnimationEventsToMainThreadOnImplThread(
141 scoped_ptr
<AnimationEventsVector
> events
) override
{}
142 bool IsInsideDraw() override
{ return false; }
143 void RenewTreePriority() override
{}
144 void PostDelayedAnimationTaskOnImplThread(const base::Closure
& task
,
145 base::TimeDelta delay
) override
{
146 animation_task_
= task
;
147 requested_animation_delay_
= delay
;
149 void DidActivateSyncTree() override
{}
150 void WillPrepareTiles() override
{}
151 void DidPrepareTiles() override
{}
152 void DidCompletePageScaleAnimationOnImplThread() override
{
153 did_complete_page_scale_animation_
= true;
155 void OnDrawForOutputSurface() override
{}
156 void PostFrameTimingEventsOnImplThread(
157 scoped_ptr
<FrameTimingTracker::CompositeTimingSet
> composite_events
,
158 scoped_ptr
<FrameTimingTracker::MainFrameTimingSet
> main_frame_events
)
161 void set_reduce_memory_result(bool reduce_memory_result
) {
162 reduce_memory_result_
= reduce_memory_result
;
165 virtual bool CreateHostImpl(const LayerTreeSettings
& settings
,
166 scoped_ptr
<OutputSurface
> output_surface
) {
167 host_impl_
= LayerTreeHostImpl::Create(
168 settings
, this, &proxy_
, &stats_instrumentation_
,
169 &shared_bitmap_manager_
, &gpu_memory_buffer_manager_
,
170 &task_graph_runner_
, 0);
171 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
172 host_impl_
->SetViewportSize(gfx::Size(10, 10));
173 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
174 // Set the BeginFrameArgs so that methods which use it are able to.
175 host_impl_
->WillBeginImplFrame(
176 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
180 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
181 root
->SetPosition(gfx::PointF());
182 root
->SetBounds(gfx::Size(10, 10));
183 root
->SetDrawsContent(true);
184 root
->draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
185 root
->SetHasRenderSurface(true);
186 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
189 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
190 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
191 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
192 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
195 static ::testing::AssertionResult
ScrollInfoContains(
196 const ScrollAndScaleSet
& scroll_info
,
198 const gfx::Vector2d
& scroll_delta
) {
199 int times_encountered
= 0;
201 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
202 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
205 if (scroll_delta
!= scroll_info
.scrolls
[i
].scroll_delta
) {
206 return ::testing::AssertionFailure()
207 << "Expected " << scroll_delta
.ToString() << ", not "
208 << scroll_info
.scrolls
[i
].scroll_delta
.ToString();
213 if (times_encountered
!= 1)
214 return ::testing::AssertionFailure() << "No layer found with id " << id
;
215 return ::testing::AssertionSuccess();
218 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
219 int times_encountered
= 0;
221 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
222 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
227 ASSERT_EQ(0, times_encountered
);
230 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
231 const gfx::Size
& content_size
) {
232 // Create both an inner viewport scroll layer and an outer viewport scroll
233 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
234 // 0x0, so the scrolls will be applied directly to the inner viewport.
235 const int kOuterViewportClipLayerId
= 116;
236 const int kOuterViewportScrollLayerId
= 117;
237 const int kContentLayerId
= 118;
238 const int kInnerViewportScrollLayerId
= 2;
239 const int kInnerViewportClipLayerId
= 4;
240 const int kPageScaleLayerId
= 5;
242 scoped_ptr
<LayerImpl
> root
=
243 LayerImpl::Create(layer_tree_impl
, 1);
244 root
->SetBounds(content_size
);
245 root
->SetPosition(gfx::PointF());
246 root
->SetHasRenderSurface(true);
248 scoped_ptr
<LayerImpl
> inner_scroll
=
249 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
250 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
251 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
253 scoped_ptr
<LayerImpl
> inner_clip
=
254 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
255 inner_clip
->SetBounds(
256 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
258 scoped_ptr
<LayerImpl
> page_scale
=
259 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
261 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
262 inner_scroll
->SetBounds(content_size
);
263 inner_scroll
->SetPosition(gfx::PointF());
265 scoped_ptr
<LayerImpl
> outer_clip
=
266 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
267 outer_clip
->SetBounds(content_size
);
268 outer_clip
->SetIsContainerForFixedPositionLayers(true);
270 scoped_ptr
<LayerImpl
> outer_scroll
=
271 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
272 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
273 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
274 outer_scroll
->SetBounds(content_size
);
275 outer_scroll
->SetPosition(gfx::PointF());
277 scoped_ptr
<LayerImpl
> contents
=
278 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
279 contents
->SetDrawsContent(true);
280 contents
->SetBounds(content_size
);
281 contents
->SetPosition(gfx::PointF());
283 outer_scroll
->AddChild(contents
.Pass());
284 outer_clip
->AddChild(outer_scroll
.Pass());
285 inner_scroll
->AddChild(outer_clip
.Pass());
286 page_scale
->AddChild(inner_scroll
.Pass());
287 inner_clip
->AddChild(page_scale
.Pass());
288 root
->AddChild(inner_clip
.Pass());
290 layer_tree_impl
->SetRootLayer(root
.Pass());
291 layer_tree_impl
->SetViewportLayersFromIds(
292 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
293 kOuterViewportScrollLayerId
);
295 layer_tree_impl
->DidBecomeActive();
296 return layer_tree_impl
->InnerViewportScrollLayer();
299 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
300 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
301 host_impl_
->active_tree(), content_size
);
302 host_impl_
->active_tree()->DidBecomeActive();
306 // Sets up a typical virtual viewport setup with one child content layer.
307 // Returns a pointer to the content layer.
308 LayerImpl
* CreateBasicVirtualViewportLayers(const gfx::Size
& viewport_size
,
309 const gfx::Size
& content_size
) {
310 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
311 // the inner a different size from the outer. We'll reuse its layer
312 // hierarchy but adjust the sizing to our needs.
313 CreateScrollAndContentsLayers(host_impl_
->active_tree(), content_size
);
315 LayerImpl
* content_layer
=
316 host_impl_
->OuterViewportScrollLayer()->children().back();
317 content_layer
->SetBounds(content_size
);
318 host_impl_
->OuterViewportScrollLayer()->SetBounds(content_size
);
320 LayerImpl
* outer_clip
= host_impl_
->OuterViewportScrollLayer()->parent();
321 outer_clip
->SetBounds(viewport_size
);
323 LayerImpl
* inner_clip_layer
=
324 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
325 inner_clip_layer
->SetBounds(viewport_size
);
326 host_impl_
->InnerViewportScrollLayer()->SetBounds(viewport_size
);
328 host_impl_
->SetViewportSize(viewport_size
);
329 host_impl_
->active_tree()->DidBecomeActive();
331 return content_layer
;
334 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
335 const gfx::Size
& size
,
336 LayerImpl
* clip_layer
) {
338 DCHECK(id
!= clip_layer
->id());
339 scoped_ptr
<LayerImpl
> layer
=
340 LayerImpl::Create(host_impl_
->active_tree(), id
);
341 layer
->SetScrollClipLayer(clip_layer
->id());
342 layer
->SetDrawsContent(true);
343 layer
->SetBounds(size
);
344 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
349 LayerTreeHostImpl::FrameData frame
;
350 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
351 host_impl_
->DrawLayers(&frame
);
352 host_impl_
->DidDrawAllLayers(frame
);
355 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
356 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
357 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
358 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
359 float device_scale_factor
);
361 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
362 // Note: It is not possible to disable the renderer once it has been set,
363 // so we do not need to test that disabling the renderer notifies us
364 // that can_draw changed.
365 EXPECT_FALSE(host_impl_
->CanDraw());
366 on_can_draw_state_changed_called_
= false;
368 // Set up the root layer, which allows us to draw.
369 SetupScrollAndContentsLayers(gfx::Size(100, 100));
370 EXPECT_TRUE(host_impl_
->CanDraw());
371 EXPECT_TRUE(on_can_draw_state_changed_called_
);
372 on_can_draw_state_changed_called_
= false;
374 // Toggle the root layer to make sure it toggles can_draw
375 host_impl_
->active_tree()->SetRootLayer(nullptr);
376 EXPECT_FALSE(host_impl_
->CanDraw());
377 EXPECT_TRUE(on_can_draw_state_changed_called_
);
378 on_can_draw_state_changed_called_
= false;
380 SetupScrollAndContentsLayers(gfx::Size(100, 100));
381 EXPECT_TRUE(host_impl_
->CanDraw());
382 EXPECT_TRUE(on_can_draw_state_changed_called_
);
383 on_can_draw_state_changed_called_
= false;
385 // Toggle the device viewport size to make sure it toggles can_draw.
386 host_impl_
->SetViewportSize(gfx::Size());
388 EXPECT_TRUE(host_impl_
->CanDraw());
390 EXPECT_FALSE(host_impl_
->CanDraw());
392 EXPECT_TRUE(on_can_draw_state_changed_called_
);
393 on_can_draw_state_changed_called_
= false;
395 host_impl_
->SetViewportSize(gfx::Size(100, 100));
396 EXPECT_TRUE(host_impl_
->CanDraw());
397 EXPECT_TRUE(on_can_draw_state_changed_called_
);
398 on_can_draw_state_changed_called_
= false;
401 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
404 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
405 return FakeOutputSurface::Create3d();
408 void DrawOneFrame() {
409 LayerTreeHostImpl::FrameData frame_data
;
410 host_impl_
->PrepareToDraw(&frame_data
);
411 host_impl_
->DidDrawAllLayers(frame_data
);
415 DebugScopedSetImplThread always_impl_thread_
;
416 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
418 TestSharedBitmapManager shared_bitmap_manager_
;
419 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
420 TestTaskGraphRunner task_graph_runner_
;
421 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
422 FakeRenderingStatsInstrumentation stats_instrumentation_
;
423 bool on_can_draw_state_changed_called_
;
424 bool did_notify_ready_to_activate_
;
425 bool did_request_commit_
;
426 bool did_request_redraw_
;
427 bool did_request_animate_
;
428 bool did_request_prepare_tiles_
;
429 bool did_complete_page_scale_animation_
;
430 bool reduce_memory_result_
;
431 base::Closure animation_task_
;
432 base::TimeDelta requested_animation_delay_
;
435 // A test fixture for new animation timelines tests.
436 class LayerTreeHostImplTimelinesTest
: public LayerTreeHostImplTest
{
438 void SetUp() override
{
439 LayerTreeSettings settings
= DefaultSettings();
440 settings
.use_compositor_animation_timelines
= true;
441 CreateHostImpl(settings
, CreateOutputSurface());
445 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
446 bool always_draw
= false;
447 CheckNotifyCalledIfCanDrawChanged(always_draw
);
450 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
451 CreateHostImpl(DefaultSettings(),
452 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
454 bool always_draw
= true;
455 CheckNotifyCalledIfCanDrawChanged(always_draw
);
458 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
459 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
461 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
462 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
465 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
467 scoped_ptr
<LayerImpl
> root
=
468 LayerImpl::Create(host_impl_
->active_tree(), 1);
469 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
470 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
471 root
->children()[1]->AddChild(
472 LayerImpl::Create(host_impl_
->active_tree(), 4));
473 root
->children()[1]->AddChild(
474 LayerImpl::Create(host_impl_
->active_tree(), 5));
475 root
->children()[1]->children()[0]->AddChild(
476 LayerImpl::Create(host_impl_
->active_tree(), 6));
477 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
479 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
481 ExpectClearedScrollDeltasRecursive(root
);
483 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
485 scroll_info
= host_impl_
->ProcessScrollDeltas();
486 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
487 ExpectClearedScrollDeltasRecursive(root
);
489 scroll_info
= host_impl_
->ProcessScrollDeltas();
490 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
491 ExpectClearedScrollDeltasRecursive(root
);
494 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
495 gfx::ScrollOffset
scroll_offset(20, 30);
496 gfx::Vector2d
scroll_delta(11, -15);
498 scoped_ptr
<LayerImpl
> root_clip
=
499 LayerImpl::Create(host_impl_
->active_tree(), 2);
500 scoped_ptr
<LayerImpl
> root
=
501 LayerImpl::Create(host_impl_
->active_tree(), 1);
502 root_clip
->SetBounds(gfx::Size(10, 10));
503 LayerImpl
* root_layer
= root
.get();
504 root_clip
->AddChild(root
.Pass());
505 root_layer
->SetBounds(gfx::Size(110, 110));
506 root_layer
->SetScrollClipLayer(root_clip
->id());
507 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
508 root_layer
->ScrollBy(scroll_delta
);
509 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
511 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
513 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
515 scroll_info
= host_impl_
->ProcessScrollDeltas();
516 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
517 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(), scroll_delta
));
519 gfx::Vector2d
scroll_delta2(-5, 27);
520 root
->ScrollBy(scroll_delta2
);
521 scroll_info
= host_impl_
->ProcessScrollDeltas();
522 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
523 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
524 scroll_delta
+ scroll_delta2
));
526 root
->ScrollBy(gfx::Vector2d());
527 scroll_info
= host_impl_
->ProcessScrollDeltas();
528 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
529 scroll_delta
+ scroll_delta2
));
532 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
533 SetupScrollAndContentsLayers(gfx::Size(100, 100));
534 host_impl_
->SetViewportSize(gfx::Size(50, 50));
537 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
538 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
539 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
540 InputHandler::WHEEL
));
541 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
542 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
543 InputHandler::WHEEL
));
544 host_impl_
->ScrollEnd();
545 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
546 InputHandler::WHEEL
));
547 EXPECT_TRUE(did_request_redraw_
);
548 EXPECT_TRUE(did_request_commit_
);
551 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
552 SetupScrollAndContentsLayers(gfx::Size(100, 100));
553 host_impl_
->SetViewportSize(gfx::Size(50, 50));
556 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
557 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
558 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
559 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
560 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
561 host_impl_
->ScrollEnd();
562 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
565 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
566 // We should not crash when trying to scroll an empty layer tree.
567 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
568 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
571 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
572 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
573 TestWebGraphicsContext3D::Create();
574 context_owned
->set_context_lost(true);
576 // Initialization will fail.
577 EXPECT_FALSE(CreateHostImpl(
578 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
580 SetupScrollAndContentsLayers(gfx::Size(100, 100));
582 // We should not crash when trying to scroll after the renderer initialization
584 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
585 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
588 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
589 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
590 host_impl_
->SetViewportSize(gfx::Size(50, 50));
593 // We should not crash if the tree is replaced while we are scrolling.
594 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
595 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
596 host_impl_
->active_tree()->DetachLayerTree();
598 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
600 // We should still be scrolling, because the scrolled layer also exists in the
602 gfx::Vector2d
scroll_delta(0, 10);
603 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
604 host_impl_
->ScrollEnd();
605 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
607 ScrollInfoContains(*scroll_info
, scroll_layer
->id(), scroll_delta
));
610 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
611 SetupScrollAndContentsLayers(gfx::Size(100, 100));
612 host_impl_
->SetViewportSize(gfx::Size(50, 50));
614 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
616 // With registered event handlers, wheel scrolls don't necessarily
617 // have to go to the main thread.
618 root
->SetHaveWheelEventHandlers(true);
619 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
620 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
621 host_impl_
->ScrollEnd();
623 // But typically the scroll-blocks-on mode will require them to.
624 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
625 SCROLL_BLOCKS_ON_START_TOUCH
);
626 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
627 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
629 // But gesture scrolls can still be handled.
630 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
631 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
632 host_impl_
->ScrollEnd();
634 // And if the handlers go away, wheel scrolls can again be processed
635 // on impl (despite the scroll-blocks-on mode).
636 root
->SetHaveWheelEventHandlers(false);
637 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
638 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
639 host_impl_
->ScrollEnd();
642 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
643 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
644 host_impl_
->SetViewportSize(gfx::Size(50, 50));
646 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
648 LayerImpl
* child
= 0;
650 scoped_ptr
<LayerImpl
> child_layer
=
651 LayerImpl::Create(host_impl_
->active_tree(), 6);
652 child
= child_layer
.get();
653 child_layer
->SetDrawsContent(true);
654 child_layer
->SetPosition(gfx::PointF(0, 20));
655 child_layer
->SetBounds(gfx::Size(50, 50));
656 scroll
->AddChild(child_layer
.Pass());
659 // Touch handler regions determine whether touch events block scroll.
660 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
661 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
662 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
663 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
664 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
666 // But they don't influence the actual handling of the scroll gestures.
667 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
668 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
669 host_impl_
->ScrollEnd();
671 // It's the union of scroll-blocks-on mode bits across all layers in the
672 // scroll paret chain that matters.
673 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
674 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
675 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
676 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
677 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
680 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
681 SetupScrollAndContentsLayers(gfx::Size(100, 100));
682 host_impl_
->SetViewportSize(gfx::Size(50, 50));
684 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
686 // With registered scroll handlers, scrolls don't generally have to go
687 // to the main thread.
688 root
->SetHaveScrollEventHandlers(true);
689 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
690 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
691 host_impl_
->ScrollEnd();
693 // Even the default scroll blocks on mode doesn't require this.
694 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
695 SCROLL_BLOCKS_ON_START_TOUCH
);
696 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
697 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
698 host_impl_
->ScrollEnd();
700 // But the page can opt in to blocking on scroll event handlers.
701 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
702 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
703 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
705 // GESTURE and WHEEL scrolls behave identically in this regard.
706 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
707 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
709 // And if the handlers go away, scrolls can again be processed on impl
710 // (despite the scroll-blocks-on mode).
711 root
->SetHaveScrollEventHandlers(false);
712 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
713 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
714 host_impl_
->ScrollEnd();
717 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
718 host_impl_
->SetViewportSize(gfx::Size(50, 50));
720 // Create a normal scrollable root layer
721 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
722 LayerImpl
* root_child
= root_scroll
->children()[0];
723 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
726 // Create two child scrollable layers
727 LayerImpl
* child1
= 0;
729 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
730 LayerImpl::Create(host_impl_
->active_tree(), 6);
731 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
732 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
733 child1
= scrollable_child_1
.get();
734 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
735 scrollable_child_1
->SetHaveWheelEventHandlers(true);
736 scrollable_child_1
->SetHaveScrollEventHandlers(true);
737 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
738 root_child
->AddChild(scrollable_child_clip_1
.Pass());
741 LayerImpl
* child2
= 0;
743 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
744 LayerImpl::Create(host_impl_
->active_tree(), 8);
745 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
746 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
747 child2
= scrollable_child_2
.get();
748 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
749 scrollable_child_2
->SetHaveWheelEventHandlers(true);
750 scrollable_child_2
->SetHaveScrollEventHandlers(true);
751 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
752 root_child
->AddChild(scrollable_child_clip_2
.Pass());
755 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
756 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
757 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
758 host_impl_
->ScrollEnd();
759 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
760 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
761 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
763 // But not those that hit only other layers.
764 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
765 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
766 host_impl_
->ScrollEnd();
768 // It's the union of bits set across the scroll ancestor chain that matters.
769 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
770 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
771 host_impl_
->ScrollEnd();
772 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
773 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
774 host_impl_
->ScrollEnd();
775 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
776 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
777 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
778 host_impl_
->ScrollEnd();
779 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
780 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
781 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
782 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
783 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
784 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
785 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
788 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
789 SetupScrollAndContentsLayers(gfx::Size(100, 100));
790 host_impl_
->SetViewportSize(gfx::Size(50, 50));
793 // Ignore the fling since no layer is being scrolled
794 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
796 // Start scrolling a layer
797 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
798 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
800 // Now the fling should go ahead since we've started scrolling a layer
801 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
804 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
805 SetupScrollAndContentsLayers(gfx::Size(100, 100));
806 host_impl_
->SetViewportSize(gfx::Size(50, 50));
809 // Ignore the fling since no layer is being scrolled
810 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
812 // Start scrolling a layer
813 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
814 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
816 // Now the fling should go ahead since we've started scrolling a layer
817 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
820 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
821 SetupScrollAndContentsLayers(gfx::Size(100, 100));
822 host_impl_
->SetViewportSize(gfx::Size(50, 50));
824 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
826 root
->SetShouldScrollOnMainThread(true);
828 // Start scrolling a layer
829 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
830 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
832 // The fling should be ignored since there's no layer being scrolled impl-side
833 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
836 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
837 SetupScrollAndContentsLayers(gfx::Size(100, 100));
838 host_impl_
->SetViewportSize(gfx::Size(50, 50));
840 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
842 root
->SetShouldScrollOnMainThread(true);
844 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
845 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
846 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
847 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
850 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
851 SetupScrollAndContentsLayers(gfx::Size(200, 200));
852 host_impl_
->SetViewportSize(gfx::Size(100, 100));
854 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
855 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
859 // All scroll types inside the non-fast scrollable region should fail.
860 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
861 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
862 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
863 InputHandler::WHEEL
));
864 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
865 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
866 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
867 InputHandler::GESTURE
));
869 // All scroll types outside this region should succeed.
870 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
871 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
872 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
873 InputHandler::GESTURE
));
874 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
875 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
876 InputHandler::GESTURE
));
877 host_impl_
->ScrollEnd();
878 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
879 InputHandler::GESTURE
));
880 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
881 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
882 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
883 InputHandler::GESTURE
));
884 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
885 host_impl_
->ScrollEnd();
886 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
887 InputHandler::GESTURE
));
890 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
891 SetupScrollAndContentsLayers(gfx::Size(200, 200));
892 host_impl_
->SetViewportSize(gfx::Size(100, 100));
894 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
895 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
896 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
900 // This point would fall into the non-fast scrollable region except that we've
901 // moved the layer down by 25 pixels.
902 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
903 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
904 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
905 InputHandler::WHEEL
));
906 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
907 host_impl_
->ScrollEnd();
909 // This point is still inside the non-fast region.
910 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
911 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
914 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
915 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
916 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
917 host_impl_
->SetViewportSize(gfx::Size(50, 50));
920 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
921 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
922 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
923 host_impl_
->ScrollEnd();
924 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
927 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
928 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
929 scroll_layer
->SetHaveScrollEventHandlers(true);
930 host_impl_
->SetViewportSize(gfx::Size(50, 50));
933 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
934 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
935 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
936 host_impl_
->ScrollEnd();
937 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
940 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
941 SetupScrollAndContentsLayers(gfx::Size(200, 200));
942 host_impl_
->SetViewportSize(gfx::Size(100, 100));
946 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
947 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
949 // Trying to scroll to the left/top will not succeed.
951 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
953 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
955 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
957 // Scrolling to the right/bottom will succeed.
959 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
961 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
963 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
965 // Scrolling to left/top will now succeed.
967 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
969 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
971 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
973 // Scrolling diagonally against an edge will succeed.
975 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
977 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
979 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
981 // Trying to scroll more than the available space will also succeed.
983 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
986 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
987 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
988 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
992 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
993 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
995 // Trying to scroll without a vertical scrollbar will fail.
996 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
997 gfx::Point(), SCROLL_FORWARD
));
998 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
999 gfx::Point(), SCROLL_BACKWARD
));
1001 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
1002 PaintedScrollbarLayerImpl::Create(
1003 host_impl_
->active_tree(),
1006 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1007 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1008 vertical_scrollbar
.get());
1010 // Trying to scroll with a vertical scrollbar will succeed.
1011 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1012 gfx::Point(), SCROLL_FORWARD
));
1013 EXPECT_FLOAT_EQ(875.f
,
1014 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1015 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1016 gfx::Point(), SCROLL_BACKWARD
));
1019 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1020 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1021 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1023 gfx::Size
overflow_size(400, 400);
1024 ASSERT_EQ(1u, scroll_layer
->children().size());
1025 LayerImpl
* overflow
= scroll_layer
->children()[0];
1026 overflow
->SetBounds(overflow_size
);
1027 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1028 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1029 overflow
->SetPosition(gfx::PointF());
1032 gfx::Point
scroll_position(10, 10);
1034 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1035 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1036 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1037 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1039 gfx::Vector2dF
scroll_delta(10, 10);
1040 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1041 host_impl_
->ScrollEnd();
1042 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1043 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1045 overflow
->set_user_scrollable_horizontal(false);
1047 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1048 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1049 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1050 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1052 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1053 host_impl_
->ScrollEnd();
1054 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1055 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1057 overflow
->set_user_scrollable_vertical(false);
1059 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1060 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1061 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1062 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1064 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1065 host_impl_
->ScrollEnd();
1066 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1067 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1070 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1071 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1072 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1075 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1076 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1077 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1079 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1080 float page_scale_factor
= 1.f
;
1082 // The impl-based pinch zoom should adjust the max scroll position.
1084 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1085 page_scale_factor
, min_page_scale
, max_page_scale
);
1086 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1087 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1089 float page_scale_delta
= 2.f
;
1091 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1092 host_impl_
->PinchGestureBegin();
1093 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1094 host_impl_
->PinchGestureEnd();
1095 host_impl_
->ScrollEnd();
1096 EXPECT_FALSE(did_request_animate_
);
1097 EXPECT_TRUE(did_request_redraw_
);
1098 EXPECT_TRUE(did_request_commit_
);
1099 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1101 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1102 host_impl_
->ProcessScrollDeltas();
1103 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1105 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1106 scroll_layer
->MaxScrollOffset().ToString());
1109 // Scrolling after a pinch gesture should always be in local space. The
1110 // scroll deltas have the page scale factor applied.
1112 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1113 page_scale_factor
, min_page_scale
, max_page_scale
);
1114 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1115 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1117 float page_scale_delta
= 2.f
;
1118 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1119 host_impl_
->PinchGestureBegin();
1120 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1121 host_impl_
->PinchGestureEnd();
1122 host_impl_
->ScrollEnd();
1124 gfx::Vector2d
scroll_delta(0, 10);
1125 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1126 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1127 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1128 host_impl_
->ScrollEnd();
1130 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1131 host_impl_
->ProcessScrollDeltas();
1132 EXPECT_TRUE(ScrollInfoContains(
1133 *scroll_info
.get(), scroll_layer
->id(),
1134 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
)));
1138 TEST_F(LayerTreeHostImplTest
, ViewportScrollOrder
) {
1139 LayerTreeSettings settings
= DefaultSettings();
1140 settings
.invert_viewport_scroll_order
= true;
1141 CreateHostImpl(settings
,
1142 CreateOutputSurface());
1143 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.25f
, 4.f
);
1145 const gfx::Size
content_size(1000, 1000);
1146 const gfx::Size
viewport_size(500, 500);
1147 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1149 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1150 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1153 gfx::Vector2dF(500, 500),
1154 outer_scroll_layer
->MaxScrollOffset());
1156 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1157 host_impl_
->PinchGestureBegin();
1158 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1159 host_impl_
->PinchGestureEnd();
1160 host_impl_
->ScrollEnd();
1162 // Sanity check - we're zoomed in, starting from the origin.
1164 gfx::Vector2dF(0, 0),
1165 outer_scroll_layer
->CurrentScrollOffset());
1167 gfx::Vector2dF(0, 0),
1168 inner_scroll_layer
->CurrentScrollOffset());
1170 // Scroll down - only the inner viewport should scroll.
1171 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1172 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1173 host_impl_
->ScrollEnd();
1176 gfx::Vector2dF(50, 50),
1177 inner_scroll_layer
->CurrentScrollOffset());
1179 gfx::Vector2dF(0, 0),
1180 outer_scroll_layer
->CurrentScrollOffset());
1182 // Scroll down - outer viewport should start scrolling after the inner is at
1184 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1185 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f
, 1000.f
));
1186 host_impl_
->ScrollEnd();
1189 gfx::Vector2dF(250, 250),
1190 inner_scroll_layer
->CurrentScrollOffset());
1192 gfx::Vector2dF(300, 300),
1193 outer_scroll_layer
->CurrentScrollOffset());
1196 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1197 // as expected. That is, scrolling during a pinch should bubble from the inner
1198 // to the outer viewport.
1199 TEST_F(LayerTreeHostImplTest
, ScrollDuringPinchGesture
) {
1200 LayerTreeSettings settings
= DefaultSettings();
1201 settings
.invert_viewport_scroll_order
= true;
1202 CreateHostImpl(settings
,
1203 CreateOutputSurface());
1204 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1206 const gfx::Size
content_size(1000, 1000);
1207 const gfx::Size
viewport_size(500, 500);
1208 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1210 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1211 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1214 gfx::Vector2dF(500, 500),
1215 outer_scroll_layer
->MaxScrollOffset());
1217 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1218 host_impl_
->PinchGestureBegin();
1220 host_impl_
->PinchGestureUpdate(2, gfx::Point(250, 250));
1222 gfx::Vector2dF(0, 0),
1223 outer_scroll_layer
->CurrentScrollOffset());
1225 gfx::Vector2dF(125, 125),
1226 inner_scroll_layer
->CurrentScrollOffset());
1228 // Needed so that the pinch is accounted for in draw properties.
1231 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f
, 10.f
));
1233 gfx::Vector2dF(0, 0),
1234 outer_scroll_layer
->CurrentScrollOffset());
1236 gfx::Vector2dF(130, 130),
1237 inner_scroll_layer
->CurrentScrollOffset());
1241 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f
, 400.f
));
1243 gfx::Vector2dF(80, 80),
1244 outer_scroll_layer
->CurrentScrollOffset());
1246 gfx::Vector2dF(250, 250),
1247 inner_scroll_layer
->CurrentScrollOffset());
1249 host_impl_
->PinchGestureEnd();
1250 host_impl_
->ScrollEnd();
1253 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1254 // a pinch zoom is anchored within a certain margin of the screen edge, we
1255 // should assume the user means to scroll into the edge of the screen.
1256 TEST_F(LayerTreeHostImplTest
, PinchZoomSnapsToScreenEdge
) {
1257 LayerTreeSettings settings
= DefaultSettings();
1258 settings
.invert_viewport_scroll_order
= true;
1259 CreateHostImpl(settings
,
1260 CreateOutputSurface());
1261 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1263 const gfx::Size
content_size(1000, 1000);
1264 const gfx::Size
viewport_size(500, 500);
1265 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1267 int offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
- 5;
1268 gfx::Point
anchor(viewport_size
.width() - offsetFromEdge
,
1269 viewport_size
.height() - offsetFromEdge
);
1271 // Pinch in within the margins. The scroll should stay exactly locked to the
1272 // bottom and right.
1273 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1274 host_impl_
->PinchGestureBegin();
1275 host_impl_
->PinchGestureUpdate(2, anchor
);
1276 host_impl_
->PinchGestureEnd();
1277 host_impl_
->ScrollEnd();
1280 gfx::Vector2dF(250, 250),
1281 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1284 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1285 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1286 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1288 // Pinch in within the margins. The scroll should stay exactly locked to the
1290 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1291 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1292 host_impl_
->PinchGestureBegin();
1293 host_impl_
->PinchGestureUpdate(2, anchor
);
1294 host_impl_
->PinchGestureEnd();
1295 host_impl_
->ScrollEnd();
1298 gfx::Vector2dF(0, 0),
1299 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1302 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1303 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1304 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1306 // Pinch in just outside the margin. There should be no snapping.
1307 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1308 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1309 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1310 host_impl_
->PinchGestureBegin();
1311 host_impl_
->PinchGestureUpdate(2, anchor
);
1312 host_impl_
->PinchGestureEnd();
1313 host_impl_
->ScrollEnd();
1316 gfx::Vector2dF(50, 50),
1317 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1320 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1321 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1322 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1324 // Pinch in just outside the margin. There should be no snapping.
1325 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1326 anchor
= gfx::Point(viewport_size
.width() - offsetFromEdge
,
1327 viewport_size
.height() - offsetFromEdge
);
1328 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1329 host_impl_
->PinchGestureBegin();
1330 host_impl_
->PinchGestureUpdate(2, anchor
);
1331 host_impl_
->PinchGestureEnd();
1332 host_impl_
->ScrollEnd();
1335 gfx::Vector2dF(200, 200),
1336 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1339 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1340 const gfx::Size
content_size(200, 200);
1341 const gfx::Size
viewport_size(100, 100);
1342 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1344 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1345 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1347 // Zoom into the page by a 2X factor
1348 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1349 float page_scale_factor
= 2.f
;
1350 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1351 page_scale_factor
, min_page_scale
, max_page_scale
);
1352 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1354 // Scroll by a small amount, there should be no bubbling up to the inner
1356 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1357 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1358 host_impl_
->ScrollEnd();
1361 gfx::Vector2dF(5, 10),
1362 outer_scroll_layer
->CurrentScrollOffset());
1365 inner_scroll_layer
->CurrentScrollOffset());
1367 // Scroll by the outer viewport's max scroll extent, there the remainder
1368 // should bubble up to the inner viewport.
1369 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1370 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f
, 200.f
));
1371 host_impl_
->ScrollEnd();
1374 gfx::Vector2dF(100, 100),
1375 outer_scroll_layer
->CurrentScrollOffset());
1377 gfx::Vector2dF(5, 10),
1378 inner_scroll_layer
->CurrentScrollOffset());
1380 // Scroll by the inner viewport's max scroll extent, it should all go to the
1382 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1383 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f
, 80.f
));
1384 host_impl_
->ScrollEnd();
1387 gfx::Vector2dF(100, 100),
1388 outer_scroll_layer
->CurrentScrollOffset());
1390 gfx::Vector2dF(50, 50),
1391 inner_scroll_layer
->CurrentScrollOffset());
1394 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1395 ui::LatencyInfo latency_info
;
1396 latency_info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0,
1398 scoped_ptr
<SwapPromise
> swap_promise(
1399 new LatencyInfoSwapPromise(latency_info
));
1401 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1402 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1403 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1404 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1405 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1406 host_impl_
->ScrollEnd();
1408 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1409 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1410 EXPECT_EQ(latency_info
.trace_id(), scroll_info
->swap_promises
[0]->TraceId());
1413 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1414 // up to the scroll_parent, rather than the stacking parent.
1415 TEST_F(LayerTreeHostImplTest
, ScrollBubblesToScrollParent
) {
1416 LayerImpl
* viewport_scroll
=
1417 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1418 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1420 // Set up two scrolling children of the root, one of which is a scroll parent
1421 // to the other. Scrolls bubbling from the child should bubble to the parent,
1422 // not the viewport.
1425 LayerImpl
*child_clip
;
1427 scoped_ptr
<LayerImpl
> scroll_parent_clip
=
1428 LayerImpl::Create(host_impl_
->active_tree(), 6);
1429 scoped_ptr
<LayerImpl
> scroll_parent
= CreateScrollableLayer(
1430 7, gfx::Size(10, 10), scroll_parent_clip
.get());
1431 parent
= scroll_parent
.get();
1432 scroll_parent_clip
->AddChild(scroll_parent
.Pass());
1434 viewport_scroll
->AddChild(scroll_parent_clip
.Pass());
1436 scoped_ptr
<LayerImpl
> scroll_child_clip
=
1437 LayerImpl::Create(host_impl_
->active_tree(), 8);
1438 scoped_ptr
<LayerImpl
> scroll_child
= CreateScrollableLayer(
1439 9, gfx::Size(10, 10), scroll_child_clip
.get());
1440 child
= scroll_child
.get();
1441 scroll_child
->SetPosition(gfx::Point(20, 20));
1442 scroll_child_clip
->AddChild(scroll_child
.Pass());
1444 child_clip
= scroll_child_clip
.get();
1445 viewport_scroll
->AddChild(scroll_child_clip
.Pass());
1447 child_clip
->SetScrollParent(parent
);
1452 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1453 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1454 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1455 host_impl_
->ScrollEnd();
1457 // The child should be fully scrolled by the first ScrollBy.
1458 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child
->CurrentScrollOffset());
1460 // The scroll_parent should receive the bubbled up second ScrollBy.
1461 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent
->CurrentScrollOffset());
1463 // The viewport shouldn't have been scrolled at all.
1465 gfx::Vector2dF(0, 0),
1466 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1468 gfx::Vector2dF(0, 0),
1469 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1473 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1474 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1475 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1476 host_impl_
->ScrollEnd();
1478 // The first ScrollBy should scroll the parent to its extent.
1479 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent
->CurrentScrollOffset());
1481 // The viewport should now be next in bubbling order.
1483 gfx::Vector2dF(2, 1),
1484 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1486 gfx::Vector2dF(0, 0),
1487 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1492 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1493 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1494 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1497 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1498 DCHECK(scroll_layer
);
1500 float min_page_scale
= 1.f
;
1501 float max_page_scale
= 4.f
;
1503 // Basic pinch zoom in gesture
1505 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1507 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1509 float page_scale_delta
= 2.f
;
1510 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1511 host_impl_
->PinchGestureBegin();
1512 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1513 host_impl_
->PinchGestureEnd();
1514 host_impl_
->ScrollEnd();
1515 EXPECT_FALSE(did_request_animate_
);
1516 EXPECT_TRUE(did_request_redraw_
);
1517 EXPECT_TRUE(did_request_commit_
);
1519 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1520 host_impl_
->ProcessScrollDeltas();
1521 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1526 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1528 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1529 float page_scale_delta
= 10.f
;
1531 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1532 host_impl_
->PinchGestureBegin();
1533 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1534 host_impl_
->PinchGestureEnd();
1535 host_impl_
->ScrollEnd();
1537 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1538 host_impl_
->ProcessScrollDeltas();
1539 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1542 // Zoom-out clamping
1544 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1546 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1547 scroll_layer
->PullDeltaForMainThread();
1548 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1550 float page_scale_delta
= 0.1f
;
1551 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1552 host_impl_
->PinchGestureBegin();
1553 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1554 host_impl_
->PinchGestureEnd();
1555 host_impl_
->ScrollEnd();
1557 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1558 host_impl_
->ProcessScrollDeltas();
1559 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1561 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1564 // Two-finger panning should not happen based on pinch events only
1566 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1568 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1569 scroll_layer
->PullDeltaForMainThread();
1570 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1572 float page_scale_delta
= 1.f
;
1573 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1574 host_impl_
->PinchGestureBegin();
1575 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1576 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1577 host_impl_
->PinchGestureEnd();
1578 host_impl_
->ScrollEnd();
1580 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1581 host_impl_
->ProcessScrollDeltas();
1582 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1583 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1586 // Two-finger panning should work with interleaved scroll events
1588 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1590 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1591 scroll_layer
->PullDeltaForMainThread();
1592 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1594 float page_scale_delta
= 1.f
;
1595 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1596 host_impl_
->PinchGestureBegin();
1597 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1598 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1599 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1600 host_impl_
->PinchGestureEnd();
1601 host_impl_
->ScrollEnd();
1603 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1604 host_impl_
->ProcessScrollDeltas();
1605 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1606 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1607 gfx::Vector2d(-10, -10)));
1610 // Two-finger panning should work when starting fully zoomed out.
1612 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1613 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1614 scroll_layer
->PullDeltaForMainThread();
1615 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1617 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1618 host_impl_
->PinchGestureBegin();
1619 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1620 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1621 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1622 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1623 host_impl_
->PinchGestureEnd();
1624 host_impl_
->ScrollEnd();
1626 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1627 host_impl_
->ProcessScrollDeltas();
1628 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1629 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1630 gfx::Vector2d(20, 20)));
1634 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1635 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1636 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1639 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1640 DCHECK(scroll_layer
);
1642 float min_page_scale
= 0.5f
;
1643 float max_page_scale
= 4.f
;
1644 base::TimeTicks start_time
= base::TimeTicks() +
1645 base::TimeDelta::FromSeconds(1);
1646 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1647 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1648 base::TimeTicks end_time
= start_time
+ duration
;
1650 // Non-anchor zoom-in
1652 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1654 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1656 did_request_redraw_
= false;
1657 did_request_animate_
= false;
1658 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1659 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1664 host_impl_
->ActivateSyncTree();
1665 EXPECT_FALSE(did_request_redraw_
);
1666 EXPECT_TRUE(did_request_animate_
);
1668 did_request_redraw_
= false;
1669 did_request_animate_
= false;
1670 host_impl_
->Animate(start_time
);
1671 EXPECT_TRUE(did_request_redraw_
);
1672 EXPECT_TRUE(did_request_animate_
);
1674 did_request_redraw_
= false;
1675 did_request_animate_
= false;
1676 host_impl_
->Animate(halfway_through_animation
);
1677 EXPECT_TRUE(did_request_redraw_
);
1678 EXPECT_TRUE(did_request_animate_
);
1680 did_request_redraw_
= false;
1681 did_request_animate_
= false;
1682 did_request_commit_
= false;
1683 host_impl_
->Animate(end_time
);
1684 EXPECT_TRUE(did_request_commit_
);
1685 EXPECT_FALSE(did_request_animate_
);
1687 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1688 host_impl_
->ProcessScrollDeltas();
1689 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1690 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1691 gfx::Vector2d(-50, -50)));
1696 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1698 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1700 did_request_redraw_
= false;
1701 did_request_animate_
= false;
1702 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1703 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1704 gfx::Vector2d(25, 25),
1708 host_impl_
->ActivateSyncTree();
1709 EXPECT_FALSE(did_request_redraw_
);
1710 EXPECT_TRUE(did_request_animate_
);
1712 did_request_redraw_
= false;
1713 did_request_animate_
= false;
1714 host_impl_
->Animate(start_time
);
1715 EXPECT_TRUE(did_request_redraw_
);
1716 EXPECT_TRUE(did_request_animate_
);
1718 did_request_redraw_
= false;
1719 did_request_commit_
= false;
1720 did_request_animate_
= false;
1721 host_impl_
->Animate(end_time
);
1722 EXPECT_TRUE(did_request_redraw_
);
1723 EXPECT_FALSE(did_request_animate_
);
1724 EXPECT_TRUE(did_request_commit_
);
1726 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1727 host_impl_
->ProcessScrollDeltas();
1728 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1729 // Pushed to (0,0) via clamping against contents layer size.
1730 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1731 gfx::Vector2d(-50, -50)));
1735 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1736 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1737 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1740 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1741 DCHECK(scroll_layer
);
1743 float min_page_scale
= 0.5f
;
1744 float max_page_scale
= 4.f
;
1745 base::TimeTicks start_time
= base::TimeTicks() +
1746 base::TimeDelta::FromSeconds(1);
1747 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1748 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1749 base::TimeTicks end_time
= start_time
+ duration
;
1751 // Anchor zoom with unchanged page scale should not change scroll or scale.
1753 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1755 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1757 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1758 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1763 host_impl_
->ActivateSyncTree();
1764 host_impl_
->Animate(start_time
);
1765 host_impl_
->Animate(halfway_through_animation
);
1766 EXPECT_TRUE(did_request_redraw_
);
1767 host_impl_
->Animate(end_time
);
1768 EXPECT_TRUE(did_request_commit_
);
1770 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1771 host_impl_
->ProcessScrollDeltas();
1772 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1773 ExpectNone(*scroll_info
, scroll_layer
->id());
1777 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1778 host_impl_
->CreatePendingTree();
1779 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
1780 CreateScrollAndContentsLayers(
1781 host_impl_
->pending_tree(),
1782 gfx::Size(100, 100));
1783 host_impl_
->ActivateSyncTree();
1786 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1787 DCHECK(scroll_layer
);
1789 float min_page_scale
= 0.5f
;
1790 float max_page_scale
= 4.f
;
1791 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1793 host_impl_
->ActivateSyncTree();
1795 base::TimeTicks start_time
= base::TimeTicks() +
1796 base::TimeDelta::FromSeconds(1);
1797 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1798 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1799 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1800 base::TimeTicks end_time
= start_time
+ duration
;
1801 float target_scale
= 2.f
;
1803 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1805 // Make sure TakePageScaleAnimation works properly.
1807 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1808 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1813 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1814 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1815 EXPECT_EQ(target_scale
, psa
->scale
);
1816 EXPECT_EQ(duration
, psa
->duration
);
1817 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1819 // Recreate the PSA. Nothing should happen here since the tree containing the
1820 // PSA hasn't been activated yet.
1821 did_request_redraw_
= false;
1822 did_request_animate_
= false;
1823 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1824 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1829 host_impl_
->Animate(halfway_through_animation
);
1830 EXPECT_FALSE(did_request_animate_
);
1831 EXPECT_FALSE(did_request_redraw_
);
1833 // Activate the sync tree. This should cause the animation to become enabled.
1834 // It should also clear the pointer on the sync tree.
1835 host_impl_
->ActivateSyncTree();
1837 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1838 EXPECT_FALSE(did_request_redraw_
);
1839 EXPECT_TRUE(did_request_animate_
);
1841 // From here on, make sure the animation runs as normal.
1842 did_request_redraw_
= false;
1843 did_request_animate_
= false;
1844 host_impl_
->Animate(start_time
);
1845 EXPECT_TRUE(did_request_redraw_
);
1846 EXPECT_TRUE(did_request_animate_
);
1848 did_request_redraw_
= false;
1849 did_request_animate_
= false;
1850 host_impl_
->Animate(third_through_animation
);
1851 EXPECT_TRUE(did_request_redraw_
);
1852 EXPECT_TRUE(did_request_animate_
);
1854 // Another activation shouldn't have any effect on the animation.
1855 host_impl_
->ActivateSyncTree();
1857 did_request_redraw_
= false;
1858 did_request_animate_
= false;
1859 host_impl_
->Animate(halfway_through_animation
);
1860 EXPECT_TRUE(did_request_redraw_
);
1861 EXPECT_TRUE(did_request_animate_
);
1863 did_request_redraw_
= false;
1864 did_request_animate_
= false;
1865 did_request_commit_
= false;
1866 host_impl_
->Animate(end_time
);
1867 EXPECT_TRUE(did_request_commit_
);
1868 EXPECT_FALSE(did_request_animate_
);
1870 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1871 host_impl_
->ProcessScrollDeltas();
1872 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
1873 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1874 gfx::Vector2d(-50, -50)));
1877 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
1878 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1879 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1882 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1883 DCHECK(scroll_layer
);
1885 base::TimeTicks start_time
=
1886 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1887 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1888 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1889 base::TimeTicks end_time
= start_time
+ duration
;
1891 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1892 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1894 did_complete_page_scale_animation_
= false;
1895 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1896 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1897 gfx::Vector2d(), false, 2.f
, duration
)));
1898 host_impl_
->ActivateSyncTree();
1899 host_impl_
->Animate(start_time
);
1900 EXPECT_FALSE(did_complete_page_scale_animation_
);
1902 host_impl_
->Animate(halfway_through_animation
);
1903 EXPECT_FALSE(did_complete_page_scale_animation_
);
1905 host_impl_
->Animate(end_time
);
1906 EXPECT_TRUE(did_complete_page_scale_animation_
);
1909 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
1911 LayerTreeHostImplOverridePhysicalTime(
1912 const LayerTreeSettings
& settings
,
1913 LayerTreeHostImplClient
* client
,
1915 SharedBitmapManager
* manager
,
1916 TaskGraphRunner
* task_graph_runner
,
1917 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
1918 : LayerTreeHostImpl(settings
,
1921 rendering_stats_instrumentation
,
1927 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
1928 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
1929 fake_current_physical_time_
);
1932 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
1933 fake_current_physical_time_
= fake_now
;
1937 base::TimeTicks fake_current_physical_time_
;
1940 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
1942 void SetupLayers(LayerTreeSettings settings
) {
1943 gfx::Size
content_size(100, 100);
1945 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
1946 new LayerTreeHostImplOverridePhysicalTime(
1947 settings
, this, &proxy_
, &shared_bitmap_manager_
,
1948 &task_graph_runner_
, &stats_instrumentation_
);
1949 host_impl_
= make_scoped_ptr(host_impl_override_time
);
1950 host_impl_
->InitializeRenderer(CreateOutputSurface());
1952 SetupScrollAndContentsLayers(content_size
);
1953 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
1954 host_impl_
->SetViewportSize(
1955 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
1957 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
1958 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 400,
1959 VERTICAL
, 10, 0, false, true);
1960 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
1962 LayerImpl
* scroll
= host_impl_
->InnerViewportScrollLayer();
1963 LayerImpl
* root
= scroll
->parent()->parent();
1964 scrollbar
->SetScrollLayerAndClipLayerByIds(scroll
->id(), root
->id());
1965 root
->AddChild(scrollbar
.Pass());
1967 host_impl_
->active_tree()->DidBecomeActive();
1971 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
1972 LayerTreeSettings settings
;
1973 settings
.scrollbar_animator
= animator
;
1974 settings
.scrollbar_fade_delay_ms
= 20;
1975 settings
.scrollbar_fade_duration_ms
= 20;
1977 SetupLayers(settings
);
1979 base::TimeTicks fake_now
= base::TimeTicks::Now();
1981 EXPECT_FALSE(did_request_animate_
);
1982 EXPECT_FALSE(did_request_redraw_
);
1983 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1984 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1986 // If no scroll happened during a scroll gesture, it should have no effect.
1987 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1988 host_impl_
->ScrollEnd();
1989 EXPECT_FALSE(did_request_animate_
);
1990 EXPECT_FALSE(did_request_redraw_
);
1991 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1992 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1994 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1996 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1997 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1998 EXPECT_FALSE(did_request_animate_
);
1999 EXPECT_TRUE(did_request_redraw_
);
2000 did_request_redraw_
= false;
2001 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2002 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2004 host_impl_
->ScrollEnd();
2005 EXPECT_FALSE(did_request_animate_
);
2006 EXPECT_FALSE(did_request_redraw_
);
2007 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2008 requested_animation_delay_
);
2009 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2011 fake_now
+= requested_animation_delay_
;
2012 requested_animation_delay_
= base::TimeDelta();
2013 animation_task_
.Run();
2014 animation_task_
= base::Closure();
2015 EXPECT_TRUE(did_request_animate_
);
2016 did_request_animate_
= false;
2017 EXPECT_FALSE(did_request_redraw_
);
2019 // After the scrollbar animation begins, we should start getting redraws.
2020 host_impl_
->Animate(fake_now
);
2021 EXPECT_TRUE(did_request_animate_
);
2022 did_request_animate_
= false;
2023 EXPECT_TRUE(did_request_redraw_
);
2024 did_request_redraw_
= false;
2025 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2026 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2028 // Setting the scroll offset outside a scroll should also cause the
2029 // scrollbar to appear and to schedule a scrollbar animation.
2030 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2031 gfx::ScrollOffset(5, 5));
2032 EXPECT_FALSE(did_request_animate_
);
2033 EXPECT_FALSE(did_request_redraw_
);
2034 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2035 requested_animation_delay_
);
2036 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2037 requested_animation_delay_
= base::TimeDelta();
2038 animation_task_
= base::Closure();
2040 // Scrollbar animation is not triggered unnecessarily.
2041 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2042 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2043 EXPECT_FALSE(did_request_animate_
);
2044 EXPECT_TRUE(did_request_redraw_
);
2045 did_request_redraw_
= false;
2046 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2047 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2049 host_impl_
->ScrollEnd();
2050 EXPECT_FALSE(did_request_animate_
);
2051 EXPECT_FALSE(did_request_redraw_
);
2052 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2053 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2055 // Changing page scale triggers scrollbar animation.
2056 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2057 host_impl_
->SetPageScaleOnActiveTree(1.1f
);
2058 EXPECT_FALSE(did_request_animate_
);
2059 EXPECT_FALSE(did_request_redraw_
);
2060 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2061 requested_animation_delay_
);
2062 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2063 requested_animation_delay_
= base::TimeDelta();
2064 animation_task_
= base::Closure();
2068 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
2069 RunTest(LayerTreeSettings::LINEAR_FADE
);
2072 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
2073 RunTest(LayerTreeSettings::THINNING
);
2076 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2077 float device_scale_factor
) {
2078 LayerTreeSettings settings
;
2079 settings
.scrollbar_fade_delay_ms
= 500;
2080 settings
.scrollbar_fade_duration_ms
= 300;
2081 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
2083 gfx::Size
viewport_size(300, 200);
2084 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
2085 gfx::ScaleSize(viewport_size
, device_scale_factor
));
2086 gfx::Size
content_size(1000, 1000);
2088 CreateHostImpl(settings
, CreateOutputSurface());
2089 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
2090 host_impl_
->SetViewportSize(device_viewport_size
);
2092 scoped_ptr
<LayerImpl
> root
=
2093 LayerImpl::Create(host_impl_
->active_tree(), 1);
2094 root
->SetBounds(viewport_size
);
2095 root
->SetHasRenderSurface(true);
2097 scoped_ptr
<LayerImpl
> scroll
=
2098 LayerImpl::Create(host_impl_
->active_tree(), 2);
2099 scroll
->SetScrollClipLayer(root
->id());
2100 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2101 scroll
->SetBounds(content_size
);
2102 scroll
->SetIsContainerForFixedPositionLayers(true);
2104 scoped_ptr
<LayerImpl
> contents
=
2105 LayerImpl::Create(host_impl_
->active_tree(), 3);
2106 contents
->SetDrawsContent(true);
2107 contents
->SetBounds(content_size
);
2109 // The scrollbar is on the right side.
2110 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
2111 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
2112 scrollbar
->SetDrawsContent(true);
2113 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
2114 scrollbar
->SetPosition(gfx::Point(285, 0));
2116 scroll
->AddChild(contents
.Pass());
2117 root
->AddChild(scroll
.Pass());
2118 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
2119 root
->AddChild(scrollbar
.Pass());
2121 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2122 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
2124 host_impl_
->active_tree()->DidBecomeActive();
2127 LayerImpl
* root_scroll
=
2128 host_impl_
->active_tree()->InnerViewportScrollLayer();
2129 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
2130 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
2131 static_cast<ScrollbarAnimationControllerThinning
*>(
2132 root_scroll
->scrollbar_animation_controller());
2133 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
2135 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
2136 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2138 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
2139 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2141 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2142 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2144 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
2145 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2146 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2148 did_request_redraw_
= false;
2149 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2150 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
2151 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2152 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
2153 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2154 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
2155 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2158 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
2159 SetupMouseMoveAtWithDeviceScale(1.f
);
2162 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
2163 SetupMouseMoveAtWithDeviceScale(2.f
);
2166 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
2167 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2168 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2169 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2172 CompositorFrameMetadata metadata
=
2173 host_impl_
->MakeCompositorFrameMetadata();
2174 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
2175 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
2176 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
2177 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2178 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2179 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2180 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2181 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2184 // Scrolling should update metadata immediately.
2185 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2186 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2187 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2189 CompositorFrameMetadata metadata
=
2190 host_impl_
->MakeCompositorFrameMetadata();
2191 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2193 host_impl_
->ScrollEnd();
2195 CompositorFrameMetadata metadata
=
2196 host_impl_
->MakeCompositorFrameMetadata();
2197 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2200 // Root "overflow: hidden" properties should be reflected on the outer
2201 // viewport scroll layer.
2203 host_impl_
->active_tree()
2204 ->OuterViewportScrollLayer()
2205 ->set_user_scrollable_horizontal(false);
2206 CompositorFrameMetadata metadata
=
2207 host_impl_
->MakeCompositorFrameMetadata();
2208 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2209 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2211 host_impl_
->active_tree()
2212 ->OuterViewportScrollLayer()
2213 ->set_user_scrollable_vertical(false);
2214 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2215 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2216 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2219 // Page scale should update metadata correctly (shrinking only the viewport).
2220 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
2221 host_impl_
->PinchGestureBegin();
2222 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
2223 host_impl_
->PinchGestureEnd();
2224 host_impl_
->ScrollEnd();
2226 CompositorFrameMetadata metadata
=
2227 host_impl_
->MakeCompositorFrameMetadata();
2228 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2229 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
2230 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
2231 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2232 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2233 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2236 // Likewise if set from the main thread.
2237 host_impl_
->ProcessScrollDeltas();
2238 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
2239 host_impl_
->SetPageScaleOnActiveTree(4.f
);
2241 CompositorFrameMetadata metadata
=
2242 host_impl_
->MakeCompositorFrameMetadata();
2243 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2244 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
2245 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
2246 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2247 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2248 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2252 class DidDrawCheckLayer
: public LayerImpl
{
2254 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2255 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2258 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2259 will_draw_called_
= true;
2260 if (will_draw_returns_false_
)
2262 return LayerImpl::WillDraw(draw_mode
, provider
);
2265 void AppendQuads(RenderPass
* render_pass
,
2266 AppendQuadsData
* append_quads_data
) override
{
2267 append_quads_called_
= true;
2268 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2271 void DidDraw(ResourceProvider
* provider
) override
{
2272 did_draw_called_
= true;
2273 LayerImpl::DidDraw(provider
);
2276 bool will_draw_called() const { return will_draw_called_
; }
2277 bool append_quads_called() const { return append_quads_called_
; }
2278 bool did_draw_called() const { return did_draw_called_
; }
2280 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2282 void ClearDidDrawCheck() {
2283 will_draw_called_
= false;
2284 append_quads_called_
= false;
2285 did_draw_called_
= false;
2288 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2290 void AddCopyRequest() {
2291 ScopedPtrVector
<CopyOutputRequest
> requests
;
2293 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2294 SetHasRenderSurface(true);
2295 PassCopyRequests(&requests
);
2299 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2300 : LayerImpl(tree_impl
, id
),
2301 will_draw_returns_false_(false),
2302 will_draw_called_(false),
2303 append_quads_called_(false),
2304 did_draw_called_(false) {
2305 SetBounds(gfx::Size(10, 10));
2306 SetDrawsContent(true);
2307 draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
2311 bool will_draw_returns_false_
;
2312 bool will_draw_called_
;
2313 bool append_quads_called_
;
2314 bool did_draw_called_
;
2317 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2318 // The root layer is always drawn, so run this test on a child layer that
2319 // will be masked out by the root layer's bounds.
2320 host_impl_
->active_tree()->SetRootLayer(
2321 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2322 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2323 host_impl_
->active_tree()->root_layer());
2325 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2326 root
->SetHasRenderSurface(true);
2327 DidDrawCheckLayer
* layer
=
2328 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2331 LayerTreeHostImpl::FrameData frame
;
2332 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2333 host_impl_
->DrawLayers(&frame
);
2334 host_impl_
->DidDrawAllLayers(frame
);
2336 EXPECT_TRUE(layer
->will_draw_called());
2337 EXPECT_TRUE(layer
->append_quads_called());
2338 EXPECT_TRUE(layer
->did_draw_called());
2341 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2344 LayerTreeHostImpl::FrameData frame
;
2346 layer
->set_will_draw_returns_false();
2347 layer
->ClearDidDrawCheck();
2349 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2350 host_impl_
->DrawLayers(&frame
);
2351 host_impl_
->DidDrawAllLayers(frame
);
2353 EXPECT_TRUE(layer
->will_draw_called());
2354 EXPECT_FALSE(layer
->append_quads_called());
2355 EXPECT_FALSE(layer
->did_draw_called());
2359 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2360 // The root layer is always drawn, so run this test on a child layer that
2361 // will be masked out by the root layer's bounds.
2362 host_impl_
->active_tree()->SetRootLayer(
2363 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2364 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2365 host_impl_
->active_tree()->root_layer());
2366 root
->SetMasksToBounds(true);
2367 root
->SetHasRenderSurface(true);
2368 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2369 DidDrawCheckLayer
* layer
=
2370 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2371 // Ensure visible_layer_rect for layer is empty.
2372 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2373 layer
->SetBounds(gfx::Size(10, 10));
2375 LayerTreeHostImpl::FrameData frame
;
2377 EXPECT_FALSE(layer
->will_draw_called());
2378 EXPECT_FALSE(layer
->did_draw_called());
2380 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
2381 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2382 host_impl_
->DrawLayers(&frame
);
2383 host_impl_
->DidDrawAllLayers(frame
);
2385 EXPECT_FALSE(layer
->will_draw_called());
2386 EXPECT_FALSE(layer
->did_draw_called());
2388 EXPECT_TRUE(layer
->visible_layer_rect().IsEmpty());
2390 // Ensure visible_layer_rect for layer is not empty
2391 layer
->SetPosition(gfx::PointF());
2393 EXPECT_FALSE(layer
->will_draw_called());
2394 EXPECT_FALSE(layer
->did_draw_called());
2396 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2397 host_impl_
->DrawLayers(&frame
);
2398 host_impl_
->DidDrawAllLayers(frame
);
2400 EXPECT_TRUE(layer
->will_draw_called());
2401 EXPECT_TRUE(layer
->did_draw_called());
2403 EXPECT_FALSE(layer
->visible_layer_rect().IsEmpty());
2406 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2407 gfx::Size
big_size(1000, 1000);
2408 host_impl_
->SetViewportSize(big_size
);
2410 host_impl_
->active_tree()->SetRootLayer(
2411 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2412 DidDrawCheckLayer
* root
=
2413 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2415 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2416 DidDrawCheckLayer
* occluded_layer
=
2417 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2419 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2420 root
->SetHasRenderSurface(true);
2421 DidDrawCheckLayer
* top_layer
=
2422 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2423 // This layer covers the occluded_layer above. Make this layer large so it can
2425 top_layer
->SetBounds(big_size
);
2426 top_layer
->SetContentsOpaque(true);
2428 LayerTreeHostImpl::FrameData frame
;
2430 EXPECT_FALSE(occluded_layer
->will_draw_called());
2431 EXPECT_FALSE(occluded_layer
->did_draw_called());
2432 EXPECT_FALSE(top_layer
->will_draw_called());
2433 EXPECT_FALSE(top_layer
->did_draw_called());
2435 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2436 host_impl_
->DrawLayers(&frame
);
2437 host_impl_
->DidDrawAllLayers(frame
);
2439 EXPECT_FALSE(occluded_layer
->will_draw_called());
2440 EXPECT_FALSE(occluded_layer
->did_draw_called());
2441 EXPECT_TRUE(top_layer
->will_draw_called());
2442 EXPECT_TRUE(top_layer
->did_draw_called());
2445 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2446 host_impl_
->active_tree()->SetRootLayer(
2447 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2448 DidDrawCheckLayer
* root
=
2449 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2451 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2452 root
->SetHasRenderSurface(true);
2453 DidDrawCheckLayer
* layer1
=
2454 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2456 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2457 DidDrawCheckLayer
* layer2
=
2458 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2460 layer1
->SetHasRenderSurface(true);
2461 layer1
->SetShouldFlattenTransform(true);
2463 EXPECT_FALSE(root
->did_draw_called());
2464 EXPECT_FALSE(layer1
->did_draw_called());
2465 EXPECT_FALSE(layer2
->did_draw_called());
2467 LayerTreeHostImpl::FrameData frame
;
2468 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2469 host_impl_
->active_tree()->root_layer());
2470 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2471 host_impl_
->DrawLayers(&frame
);
2472 host_impl_
->DidDrawAllLayers(frame
);
2474 EXPECT_TRUE(root
->did_draw_called());
2475 EXPECT_TRUE(layer1
->did_draw_called());
2476 EXPECT_TRUE(layer2
->did_draw_called());
2478 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2479 EXPECT_TRUE(layer1
->render_surface());
2482 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2484 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2487 bool had_incomplete_tile
,
2489 ResourceProvider
* resource_provider
) {
2490 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2493 had_incomplete_tile
,
2495 resource_provider
));
2498 void AppendQuads(RenderPass
* render_pass
,
2499 AppendQuadsData
* append_quads_data
) override
{
2500 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2501 if (had_incomplete_tile_
)
2502 append_quads_data
->num_incomplete_tiles
++;
2504 append_quads_data
->num_missing_tiles
++;
2508 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2511 bool had_incomplete_tile
,
2513 ResourceProvider
* resource_provider
)
2514 : DidDrawCheckLayer(tree_impl
, id
),
2515 tile_missing_(tile_missing
),
2516 had_incomplete_tile_(had_incomplete_tile
) {
2518 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2522 bool had_incomplete_tile_
;
2525 struct PrepareToDrawSuccessTestCase
{
2527 bool has_missing_tile
= false;
2528 bool has_incomplete_tile
= false;
2529 bool is_animating
= false;
2530 bool has_copy_request
= false;
2532 bool high_res_required
= false;
2534 State layer_between
;
2536 DrawResult expected_result
;
2538 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2539 : expected_result(result
) {}
2542 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2543 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2546 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2547 // 1. Animated layer first.
2548 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2549 cases
.back().layer_before
.is_animating
= true;
2550 // 2. Animated layer between.
2551 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2552 cases
.back().layer_between
.is_animating
= true;
2553 // 3. Animated layer last.
2554 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2555 cases
.back().layer_after
.is_animating
= true;
2556 // 4. Missing tile first.
2557 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2558 cases
.back().layer_before
.has_missing_tile
= true;
2559 // 5. Missing tile between.
2560 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2561 cases
.back().layer_between
.has_missing_tile
= true;
2562 // 6. Missing tile last.
2563 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2564 cases
.back().layer_after
.has_missing_tile
= true;
2565 // 7. Incomplete tile first.
2566 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2567 cases
.back().layer_before
.has_incomplete_tile
= true;
2568 // 8. Incomplete tile between.
2569 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2570 cases
.back().layer_between
.has_incomplete_tile
= true;
2571 // 9. Incomplete tile last.
2572 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2573 cases
.back().layer_after
.has_incomplete_tile
= true;
2574 // 10. Animation with missing tile.
2576 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2577 cases
.back().layer_between
.has_missing_tile
= true;
2578 cases
.back().layer_between
.is_animating
= true;
2579 // 11. Animation with incomplete tile.
2580 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2581 cases
.back().layer_between
.has_incomplete_tile
= true;
2582 cases
.back().layer_between
.is_animating
= true;
2584 // 12. High res required.
2585 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2586 cases
.back().high_res_required
= true;
2587 // 13. High res required with incomplete tile.
2589 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2590 cases
.back().high_res_required
= true;
2591 cases
.back().layer_between
.has_incomplete_tile
= true;
2592 // 14. High res required with missing tile.
2594 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2595 cases
.back().high_res_required
= true;
2596 cases
.back().layer_between
.has_missing_tile
= true;
2598 // 15. High res required is higher priority than animating missing tiles.
2600 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2601 cases
.back().high_res_required
= true;
2602 cases
.back().layer_between
.has_missing_tile
= true;
2603 cases
.back().layer_after
.has_missing_tile
= true;
2604 cases
.back().layer_after
.is_animating
= true;
2605 // 16. High res required is higher priority than animating missing tiles.
2607 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2608 cases
.back().high_res_required
= true;
2609 cases
.back().layer_between
.has_missing_tile
= true;
2610 cases
.back().layer_before
.has_missing_tile
= true;
2611 cases
.back().layer_before
.is_animating
= true;
2613 host_impl_
->active_tree()->SetRootLayer(
2614 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2615 DidDrawCheckLayer
* root
=
2616 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2617 root
->SetHasRenderSurface(true);
2619 LayerTreeHostImpl::FrameData frame
;
2620 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2621 host_impl_
->DrawLayers(&frame
);
2622 host_impl_
->DidDrawAllLayers(frame
);
2623 host_impl_
->SwapBuffers(frame
);
2625 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2626 const auto& testcase
= cases
[i
];
2627 std::vector
<LayerImpl
*> to_remove
;
2628 for (auto* child
: root
->children())
2629 to_remove
.push_back(child
);
2630 for (auto* child
: to_remove
)
2631 root
->RemoveChild(child
);
2633 std::ostringstream scope
;
2634 scope
<< "Test case: " << i
;
2635 SCOPED_TRACE(scope
.str());
2637 root
->AddChild(MissingTextureAnimatingLayer::Create(
2638 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2639 testcase
.layer_before
.has_incomplete_tile
,
2640 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2641 DidDrawCheckLayer
* before
=
2642 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2643 if (testcase
.layer_before
.has_copy_request
)
2644 before
->AddCopyRequest();
2646 root
->AddChild(MissingTextureAnimatingLayer::Create(
2647 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2648 testcase
.layer_between
.has_incomplete_tile
,
2649 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2650 DidDrawCheckLayer
* between
=
2651 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2652 if (testcase
.layer_between
.has_copy_request
)
2653 between
->AddCopyRequest();
2655 root
->AddChild(MissingTextureAnimatingLayer::Create(
2656 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2657 testcase
.layer_after
.has_incomplete_tile
,
2658 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2659 DidDrawCheckLayer
* after
=
2660 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2661 if (testcase
.layer_after
.has_copy_request
)
2662 after
->AddCopyRequest();
2664 if (testcase
.high_res_required
)
2665 host_impl_
->SetRequiresHighResToDraw();
2667 LayerTreeHostImpl::FrameData frame
;
2668 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2669 host_impl_
->DrawLayers(&frame
);
2670 host_impl_
->DidDrawAllLayers(frame
);
2671 host_impl_
->SwapBuffers(frame
);
2675 TEST_F(LayerTreeHostImplTest
,
2676 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2677 CreateHostImpl(DefaultSettings(),
2678 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2679 EXPECT_TRUE(host_impl_
->output_surface()
2681 .draw_and_swap_full_viewport_every_frame
);
2683 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2686 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2687 // 1. Animation with missing tile.
2688 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2689 cases
.back().layer_between
.has_missing_tile
= true;
2690 cases
.back().layer_between
.is_animating
= true;
2691 // 2. High res required with incomplete tile.
2692 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2693 cases
.back().high_res_required
= true;
2694 cases
.back().layer_between
.has_incomplete_tile
= true;
2695 // 3. High res required with missing tile.
2696 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2697 cases
.back().high_res_required
= true;
2698 cases
.back().layer_between
.has_missing_tile
= true;
2700 host_impl_
->active_tree()->SetRootLayer(
2701 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2702 DidDrawCheckLayer
* root
=
2703 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2704 root
->SetHasRenderSurface(true);
2706 LayerTreeHostImpl::FrameData frame
;
2707 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2708 host_impl_
->DrawLayers(&frame
);
2709 host_impl_
->DidDrawAllLayers(frame
);
2710 host_impl_
->SwapBuffers(frame
);
2712 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2713 const auto& testcase
= cases
[i
];
2714 std::vector
<LayerImpl
*> to_remove
;
2715 for (auto* child
: root
->children())
2716 to_remove
.push_back(child
);
2717 for (auto* child
: to_remove
)
2718 root
->RemoveChild(child
);
2720 std::ostringstream scope
;
2721 scope
<< "Test case: " << i
;
2722 SCOPED_TRACE(scope
.str());
2724 root
->AddChild(MissingTextureAnimatingLayer::Create(
2725 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2726 testcase
.layer_before
.has_incomplete_tile
,
2727 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2728 DidDrawCheckLayer
* before
=
2729 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2730 if (testcase
.layer_before
.has_copy_request
)
2731 before
->AddCopyRequest();
2733 root
->AddChild(MissingTextureAnimatingLayer::Create(
2734 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2735 testcase
.layer_between
.has_incomplete_tile
,
2736 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2737 DidDrawCheckLayer
* between
=
2738 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2739 if (testcase
.layer_between
.has_copy_request
)
2740 between
->AddCopyRequest();
2742 root
->AddChild(MissingTextureAnimatingLayer::Create(
2743 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2744 testcase
.layer_after
.has_incomplete_tile
,
2745 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2746 DidDrawCheckLayer
* after
=
2747 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2748 if (testcase
.layer_after
.has_copy_request
)
2749 after
->AddCopyRequest();
2751 if (testcase
.high_res_required
)
2752 host_impl_
->SetRequiresHighResToDraw();
2754 LayerTreeHostImpl::FrameData frame
;
2755 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2756 host_impl_
->DrawLayers(&frame
);
2757 host_impl_
->DidDrawAllLayers(frame
);
2758 host_impl_
->SwapBuffers(frame
);
2762 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2763 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2764 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2765 root
->SetHasRenderSurface(true);
2766 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2769 // Scroll event is ignored because layer is not scrollable.
2770 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2771 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2772 EXPECT_FALSE(did_request_redraw_
);
2773 EXPECT_FALSE(did_request_commit_
);
2776 TEST_F(LayerTreeHostImplTest
, ClampingAfterActivation
) {
2777 host_impl_
->CreatePendingTree();
2778 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2779 CreateScrollAndContentsLayers(host_impl_
->pending_tree(),
2780 gfx::Size(100, 100));
2781 host_impl_
->ActivateSyncTree();
2783 host_impl_
->CreatePendingTree();
2784 const gfx::ScrollOffset pending_scroll
= gfx::ScrollOffset(-100, -100);
2785 LayerImpl
* active_outer_layer
=
2786 host_impl_
->active_tree()->OuterViewportScrollLayer();
2787 LayerImpl
* pending_outer_layer
=
2788 host_impl_
->pending_tree()->OuterViewportScrollLayer();
2789 pending_outer_layer
->PushScrollOffsetFromMainThread(pending_scroll
);
2791 host_impl_
->ActivateSyncTree();
2792 // Scrolloffsets on the active tree will be clamped after activation.
2793 EXPECT_EQ(active_outer_layer
->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
2796 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
2798 LayerTreeHostImplTopControlsTest()
2799 // Make the clip size the same as the layer (content) size so the layer is
2801 : layer_size_(10, 10),
2802 clip_size_(layer_size_
),
2803 top_controls_height_(50) {
2804 viewport_size_
= gfx::Size(clip_size_
.width(),
2805 clip_size_
.height() + top_controls_height_
);
2808 bool CreateHostImpl(const LayerTreeSettings
& settings
,
2809 scoped_ptr
<OutputSurface
> output_surface
) override
{
2811 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
2813 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
2814 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2815 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2820 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2821 const gfx::Size
& inner_viewport_size
,
2822 const gfx::Size
& outer_viewport_size
,
2823 const gfx::Size
& scroll_layer_size
) {
2824 CreateHostImpl(settings_
, CreateOutputSurface());
2825 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2826 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2827 host_impl_
->DidChangeTopControlsPosition();
2829 scoped_ptr
<LayerImpl
> root
=
2830 LayerImpl::Create(host_impl_
->active_tree(), 1);
2831 scoped_ptr
<LayerImpl
> root_clip
=
2832 LayerImpl::Create(host_impl_
->active_tree(), 2);
2833 scoped_ptr
<LayerImpl
> page_scale
=
2834 LayerImpl::Create(host_impl_
->active_tree(), 3);
2836 scoped_ptr
<LayerImpl
> outer_scroll
=
2837 LayerImpl::Create(host_impl_
->active_tree(), 4);
2838 scoped_ptr
<LayerImpl
> outer_clip
=
2839 LayerImpl::Create(host_impl_
->active_tree(), 5);
2841 root_clip
->SetBounds(inner_viewport_size
);
2842 root
->SetScrollClipLayer(root_clip
->id());
2843 root
->SetBounds(outer_viewport_size
);
2844 root
->SetPosition(gfx::PointF());
2845 root
->SetDrawsContent(false);
2846 root
->SetIsContainerForFixedPositionLayers(true);
2847 root_clip
->SetHasRenderSurface(true);
2848 outer_clip
->SetBounds(outer_viewport_size
);
2849 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
2850 outer_scroll
->SetBounds(scroll_layer_size
);
2851 outer_scroll
->SetPosition(gfx::PointF());
2852 outer_scroll
->SetDrawsContent(false);
2853 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
2855 int inner_viewport_scroll_layer_id
= root
->id();
2856 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
2857 int page_scale_layer_id
= page_scale
->id();
2859 outer_clip
->AddChild(outer_scroll
.Pass());
2860 root
->AddChild(outer_clip
.Pass());
2861 page_scale
->AddChild(root
.Pass());
2862 root_clip
->AddChild(page_scale
.Pass());
2864 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2865 host_impl_
->active_tree()->SetViewportLayersFromIds(
2866 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2867 outer_viewport_scroll_layer_id
);
2869 host_impl_
->SetViewportSize(inner_viewport_size
);
2870 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2871 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
2875 gfx::Size layer_size_
;
2876 gfx::Size clip_size_
;
2877 gfx::Size viewport_size_
;
2878 float top_controls_height_
;
2880 LayerTreeSettings settings_
;
2881 }; // class LayerTreeHostImplTopControlsTest
2883 // Tests that, on a page with content the same size as the viewport, hiding
2884 // the top controls also increases the ScrollableSize (i.e. the content size).
2885 // Since the viewport got larger, the effective scrollable "content" also did.
2886 // This ensures, for one thing, that the overscroll glow is shown in the right
2888 TEST_F(LayerTreeHostImplTopControlsTest
,
2889 HidingTopControlsExpandsScrollableSize
) {
2890 SetupTopControlsAndScrollLayerWithVirtualViewport(
2891 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
2893 LayerTreeImpl
* active_tree
= host_impl_
->active_tree();
2895 // Create a content layer beneath the outer viewport scroll layer.
2896 int id
= host_impl_
->OuterViewportScrollLayer()->id();
2897 host_impl_
->OuterViewportScrollLayer()->AddChild(
2898 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2));
2899 LayerImpl
* content
= active_tree
->OuterViewportScrollLayer()->children()[0];
2900 content
->SetBounds(gfx::Size(50, 50));
2904 LayerImpl
* inner_container
= active_tree
->InnerViewportContainerLayer();
2905 LayerImpl
* outer_container
= active_tree
->OuterViewportContainerLayer();
2907 // The top controls should start off showing so the viewport should be shrunk.
2908 ASSERT_EQ(gfx::Size(50, 50), inner_container
->bounds());
2909 ASSERT_EQ(gfx::Size(50, 50), outer_container
->bounds());
2911 EXPECT_EQ(gfx::SizeF(50, 50), active_tree
->ScrollableSize());
2913 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2914 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2916 host_impl_
->top_controls_manager()->ScrollBegin();
2918 // Hide the top controls by a bit, the scrollable size should increase but the
2919 // actual content bounds shouldn't.
2921 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
2922 ASSERT_EQ(gfx::Size(50, 75), inner_container
->bounds());
2923 ASSERT_EQ(gfx::Size(50, 75), outer_container
->bounds());
2924 EXPECT_EQ(gfx::SizeF(50, 75), active_tree
->ScrollableSize());
2925 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
2928 // Fully hide the top controls.
2930 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
2931 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
2932 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
2933 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
2934 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
2937 // Scrolling additionally shouldn't have any effect.
2939 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
2940 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
2941 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
2942 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
2943 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
2946 host_impl_
->top_controls_manager()->ScrollEnd();
2947 host_impl_
->ScrollEnd();
2950 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
2951 SetupTopControlsAndScrollLayerWithVirtualViewport(
2952 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2955 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2956 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2958 // Make the test scroll delta a fractional amount, to verify that the
2959 // fixed container size delta is (1) non-zero, and (2) fractional, and
2960 // (3) matches the movement of the top controls.
2961 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
2962 host_impl_
->top_controls_manager()->ScrollBegin();
2963 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2964 host_impl_
->top_controls_manager()->ScrollEnd();
2966 LayerImpl
* inner_viewport_scroll_layer
=
2967 host_impl_
->active_tree()->InnerViewportScrollLayer();
2968 DCHECK(inner_viewport_scroll_layer
);
2969 host_impl_
->ScrollEnd();
2970 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
2971 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
2974 // In this test, the outer viewport is initially unscrollable. We test that a
2975 // scroll initiated on the inner viewport, causing the top controls to show and
2976 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2977 TEST_F(LayerTreeHostImplTopControlsTest
,
2978 TopControlsOuterViewportBecomesScrollable
) {
2979 SetupTopControlsAndScrollLayerWithVirtualViewport(
2980 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2983 LayerImpl
* inner_scroll
=
2984 host_impl_
->active_tree()->InnerViewportScrollLayer();
2985 LayerImpl
* inner_container
=
2986 host_impl_
->active_tree()->InnerViewportContainerLayer();
2987 LayerImpl
* outer_scroll
=
2988 host_impl_
->active_tree()->OuterViewportScrollLayer();
2989 LayerImpl
* outer_container
=
2990 host_impl_
->active_tree()->OuterViewportContainerLayer();
2992 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2993 outer_scroll
->SetDrawsContent(true);
2994 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
2996 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2997 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2998 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
3000 // The entire scroll delta should have been used to hide the top controls.
3001 // The viewport layers should be resized back to their full sizes.
3002 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3003 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3004 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
3005 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
3007 // The inner viewport should be scrollable by 50px * page_scale.
3008 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
3009 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
3010 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3011 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
3013 host_impl_
->ScrollEnd();
3015 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3016 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3017 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
3019 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3021 // The entire scroll delta should have been used to show the top controls.
3022 // The outer viewport should be resized to accomodate and scrolled to the
3023 // bottom of the document to keep the viewport in place.
3024 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3025 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
3026 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
3027 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3028 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3030 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3031 // since it wasn't scrollable when the scroll began.
3032 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
3033 EXPECT_EQ(15.f
, outer_scroll
->CurrentScrollOffset().y());
3034 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3036 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
3037 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3038 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3040 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3041 host_impl_
->ScrollEnd();
3043 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3044 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3047 // Test that the fixed position container delta is appropriately adjusted
3048 // by the top controls showing/hiding and page scale doesn't affect it.
3049 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
3050 SetupTopControlsAndScrollLayerWithVirtualViewport(
3051 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3053 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3055 float page_scale
= 1.5f
;
3056 LayerImpl
* outer_viewport_scroll_layer
=
3057 host_impl_
->active_tree()->OuterViewportScrollLayer();
3059 // Zoom in, since the fixed container is the outer viewport, the delta should
3061 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3063 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3064 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3066 // Scroll down, the top controls hiding should expand the viewport size so
3067 // the delta should be equal to the scroll distance.
3068 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
3069 host_impl_
->top_controls_manager()->ScrollBegin();
3070 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3071 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
3072 host_impl_
->top_controls_manager()->ContentTopOffset());
3073 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3074 outer_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3075 host_impl_
->ScrollEnd();
3077 // Scroll past the maximum extent. The delta shouldn't be greater than the
3078 // top controls height.
3079 host_impl_
->top_controls_manager()->ScrollBegin();
3080 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3081 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3082 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3083 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3084 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
3085 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3086 host_impl_
->ScrollEnd();
3088 // Scroll in the direction to make the top controls show.
3089 host_impl_
->top_controls_manager()->ScrollBegin();
3090 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
3091 EXPECT_EQ(top_controls_scroll_delta
.y(),
3092 host_impl_
->top_controls_manager()->ContentTopOffset());
3094 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
3095 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3096 host_impl_
->top_controls_manager()->ScrollEnd();
3099 // Test that if only the top controls are scrolled, we shouldn't request a
3101 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsDontTriggerCommit
) {
3102 SetupTopControlsAndScrollLayerWithVirtualViewport(
3103 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3106 // Show top controls
3107 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3109 // Scroll 25px to hide top controls
3110 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3111 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3112 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3113 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3114 EXPECT_FALSE(did_request_commit_
);
3117 // Test that if a scrollable sublayer doesn't consume the scroll,
3118 // top controls should hide when scrolling down.
3119 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
3120 gfx::Size
sub_content_size(100, 400);
3121 gfx::Size
sub_content_layer_size(100, 300);
3122 SetupTopControlsAndScrollLayerWithVirtualViewport(
3123 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3126 // Show top controls
3127 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3129 LayerImpl
* outer_viewport_scroll_layer
=
3130 host_impl_
->active_tree()->OuterViewportScrollLayer();
3131 int id
= outer_viewport_scroll_layer
->id();
3133 scoped_ptr
<LayerImpl
> child
=
3134 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
3135 scoped_ptr
<LayerImpl
> child_clip
=
3136 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
3138 child_clip
->SetBounds(sub_content_layer_size
);
3139 child
->SetScrollClipLayer(child_clip
->id());
3140 child
->SetBounds(sub_content_size
);
3141 child
->SetPosition(gfx::PointF());
3142 child
->SetDrawsContent(true);
3143 child
->SetIsContainerForFixedPositionLayers(true);
3145 // scroll child to limit
3146 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
3147 child_clip
->AddChild(child
.Pass());
3148 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
3150 // Scroll 25px to hide top controls
3151 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3152 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3153 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3154 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3155 host_impl_
->ScrollEnd();
3157 // Top controls should be hidden
3158 EXPECT_EQ(scroll_delta
.y(),
3159 top_controls_height_
-
3160 host_impl_
->top_controls_manager()->ContentTopOffset());
3163 // Ensure setting the top controls position explicitly using the setters on the
3164 // TreeImpl correctly affects the top controls manager and viewport bounds.
3165 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
3166 CreateHostImpl(settings_
, CreateOutputSurface());
3167 SetupTopControlsAndScrollLayerWithVirtualViewport(
3168 layer_size_
, layer_size_
, layer_size_
);
3171 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3172 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3173 30.f
/ top_controls_height_
);
3174 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3175 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3176 EXPECT_FLOAT_EQ(-20.f
,
3177 host_impl_
->top_controls_manager()->ControlsTopOffset());
3179 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3180 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3181 EXPECT_FLOAT_EQ(-50.f
,
3182 host_impl_
->top_controls_manager()->ControlsTopOffset());
3184 host_impl_
->DidChangeTopControlsPosition();
3186 // Now that top controls have moved, expect the clip to resize.
3187 LayerImpl
* inner_clip_ptr
=
3188 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3189 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3192 // Test that the top_controls delta and sent delta are appropriately
3193 // applied on sync tree activation. The total top controls offset shouldn't
3194 // change after the activation.
3195 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
3196 CreateHostImpl(settings_
, CreateOutputSurface());
3197 SetupTopControlsAndScrollLayerWithVirtualViewport(
3198 layer_size_
, layer_size_
, layer_size_
);
3201 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3202 20.f
/ top_controls_height_
);
3203 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3204 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
3205 15.f
/ top_controls_height_
);
3206 host_impl_
->active_tree()
3207 ->top_controls_shown_ratio()
3208 ->PullDeltaForMainThread();
3209 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3210 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
3211 top_controls_height_
);
3213 host_impl_
->DidChangeTopControlsPosition();
3214 LayerImpl
* inner_clip_ptr
=
3215 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3216 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3217 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3219 host_impl_
->ActivateSyncTree();
3221 inner_clip_ptr
= host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3222 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3223 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3226 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
3227 top_controls_height_
);
3230 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3231 top_controls_height_
);
3234 // Test that changing the top controls layout height is correctly applied to
3235 // the inner viewport container bounds. That is, the top controls layout
3236 // height is the amount that the inner viewport container was shrunk outside
3237 // the compositor to accommodate the top controls.
3238 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
3239 CreateHostImpl(settings_
, CreateOutputSurface());
3240 SetupTopControlsAndScrollLayerWithVirtualViewport(
3241 layer_size_
, layer_size_
, layer_size_
);
3244 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
3245 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3247 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3249 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3250 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3252 host_impl_
->DidChangeTopControlsPosition();
3253 LayerImpl
* inner_clip_ptr
=
3254 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3255 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3256 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3258 host_impl_
->sync_tree()->root_layer()->SetBounds(
3259 gfx::Size(inner_clip_ptr
->bounds().width(),
3260 inner_clip_ptr
->bounds().height() - 50.f
));
3262 host_impl_
->ActivateSyncTree();
3265 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3266 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3268 // The total bounds should remain unchanged since the bounds delta should
3269 // account for the difference between the layout height and the current
3270 // top controls offset.
3271 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3272 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), inner_clip_ptr
->bounds_delta());
3274 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3275 host_impl_
->DidChangeTopControlsPosition();
3277 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
3278 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
3279 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3280 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), inner_clip_ptr
->bounds_delta());
3281 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
3282 inner_clip_ptr
->bounds());
3285 // Test that showing/hiding the top controls when the viewport is fully scrolled
3286 // doesn't incorrectly change the viewport offset due to clamping from changing
3288 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
3289 SetupTopControlsAndScrollLayerWithVirtualViewport(
3290 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3293 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3295 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3296 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3298 // Scroll the viewports to max scroll offset.
3299 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3300 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3302 gfx::ScrollOffset viewport_offset
=
3303 host_impl_
->active_tree()->TotalScrollOffset();
3304 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
3306 // Hide the top controls by 25px.
3307 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3308 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3309 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3310 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3312 // scrolling down at the max extents no longer hides the top controls
3313 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3315 // forcefully hide the top controls by 25px
3316 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3317 host_impl_
->ScrollEnd();
3319 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3320 top_controls_height_
-
3321 host_impl_
->top_controls_manager()->ContentTopOffset());
3323 inner_scroll
->ClampScrollToMaxScrollOffset();
3324 outer_scroll
->ClampScrollToMaxScrollOffset();
3326 // We should still be fully scrolled.
3327 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3328 host_impl_
->active_tree()->TotalScrollOffset());
3330 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3332 // Bring the top controls down by 25px.
3333 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3334 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3335 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3336 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3337 host_impl_
->ScrollEnd();
3339 // The viewport offset shouldn't have changed.
3340 EXPECT_EQ(viewport_offset
,
3341 host_impl_
->active_tree()->TotalScrollOffset());
3343 // Scroll the viewports to max scroll offset.
3344 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3345 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3346 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3347 host_impl_
->active_tree()->TotalScrollOffset());
3350 // Test that the top controls coming in and out maintains the same aspect ratio
3351 // between the inner and outer viewports.
3352 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3353 SetupTopControlsAndScrollLayerWithVirtualViewport(
3354 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3355 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 2.f
);
3358 EXPECT_FLOAT_EQ(top_controls_height_
,
3359 host_impl_
->top_controls_manager()->ContentTopOffset());
3361 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3362 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3363 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3364 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3365 host_impl_
->ScrollEnd();
3367 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3368 top_controls_height_
-
3369 host_impl_
->top_controls_manager()->ContentTopOffset());
3371 // Top controls were hidden by 25px so the inner viewport should have expanded
3373 LayerImpl
* outer_container
=
3374 host_impl_
->active_tree()->OuterViewportContainerLayer();
3375 LayerImpl
* inner_container
=
3376 host_impl_
->active_tree()->InnerViewportContainerLayer();
3377 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3379 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3380 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3381 inner_container
->BoundsForScrolling().height();
3382 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3383 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3385 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3388 // Test that scrolling the outer viewport affects the top controls.
3389 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3390 SetupTopControlsAndScrollLayerWithVirtualViewport(
3391 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3394 EXPECT_EQ(top_controls_height_
,
3395 host_impl_
->top_controls_manager()->ContentTopOffset());
3397 // Send a gesture scroll that will scroll the outer viewport, make sure the
3398 // top controls get scrolled.
3399 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3400 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3401 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3402 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3403 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3404 host_impl_
->CurrentlyScrollingLayer());
3405 host_impl_
->ScrollEnd();
3407 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3408 top_controls_height_
-
3409 host_impl_
->top_controls_manager()->ContentTopOffset());
3411 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3412 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3413 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3414 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3416 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3417 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3418 host_impl_
->CurrentlyScrollingLayer());
3420 host_impl_
->ScrollEnd();
3422 // Position the viewports such that the inner viewport will be scrolled.
3423 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3424 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3425 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3427 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3428 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3429 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3430 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3432 EXPECT_EQ(top_controls_height_
,
3433 host_impl_
->top_controls_manager()->ContentTopOffset());
3435 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3436 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3438 host_impl_
->ScrollEnd();
3441 TEST_F(LayerTreeHostImplTopControlsTest
,
3442 ScrollNonScrollableRootWithTopControls
) {
3443 CreateHostImpl(settings_
, CreateOutputSurface());
3444 SetupTopControlsAndScrollLayerWithVirtualViewport(
3445 layer_size_
, layer_size_
, layer_size_
);
3448 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3449 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3451 host_impl_
->top_controls_manager()->ScrollBegin();
3452 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3453 host_impl_
->top_controls_manager()->ScrollEnd();
3454 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3455 // Now that top controls have moved, expect the clip to resize.
3456 LayerImpl
* inner_clip_ptr
=
3457 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3458 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3460 host_impl_
->ScrollEnd();
3462 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3463 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3465 float scroll_increment_y
= -25.f
;
3466 host_impl_
->top_controls_manager()->ScrollBegin();
3467 host_impl_
->top_controls_manager()->ScrollBy(
3468 gfx::Vector2dF(0.f
, scroll_increment_y
));
3469 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3470 host_impl_
->top_controls_manager()->ContentTopOffset());
3471 // Now that top controls have moved, expect the clip to resize.
3472 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3473 viewport_size_
.height() + scroll_increment_y
),
3474 inner_clip_ptr
->bounds());
3476 host_impl_
->top_controls_manager()->ScrollBy(
3477 gfx::Vector2dF(0.f
, scroll_increment_y
));
3478 host_impl_
->top_controls_manager()->ScrollEnd();
3479 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3480 host_impl_
->top_controls_manager()->ContentTopOffset());
3481 // Now that top controls have moved, expect the clip to resize.
3482 EXPECT_EQ(clip_size_
, inner_clip_ptr
->bounds());
3484 host_impl_
->ScrollEnd();
3486 // Verify the layer is once-again non-scrollable.
3488 gfx::ScrollOffset(),
3489 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3491 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3492 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3495 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3496 // Test the configuration where a non-composited root layer is embedded in a
3497 // scrollable outer layer.
3498 gfx::Size
surface_size(10, 10);
3499 gfx::Size
contents_size(20, 20);
3501 scoped_ptr
<LayerImpl
> content_layer
=
3502 LayerImpl::Create(host_impl_
->active_tree(), 1);
3503 content_layer
->SetDrawsContent(true);
3504 content_layer
->SetPosition(gfx::PointF());
3505 content_layer
->SetBounds(contents_size
);
3507 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3508 LayerImpl::Create(host_impl_
->active_tree(), 3);
3509 scroll_clip_layer
->SetBounds(surface_size
);
3511 scoped_ptr
<LayerImpl
> scroll_layer
=
3512 LayerImpl::Create(host_impl_
->active_tree(), 2);
3513 scroll_layer
->SetScrollClipLayer(3);
3514 scroll_layer
->SetBounds(contents_size
);
3515 scroll_layer
->SetPosition(gfx::PointF());
3516 scroll_layer
->AddChild(content_layer
.Pass());
3517 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3519 scroll_clip_layer
->SetHasRenderSurface(true);
3520 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3521 host_impl_
->SetViewportSize(surface_size
);
3524 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3525 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3526 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3527 host_impl_
->ScrollEnd();
3528 EXPECT_TRUE(did_request_redraw_
);
3529 EXPECT_TRUE(did_request_commit_
);
3532 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3533 gfx::Size
surface_size(10, 10);
3534 gfx::Size
contents_size(20, 20);
3535 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3536 root
->SetBounds(surface_size
);
3537 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3538 root
->SetHasRenderSurface(true);
3539 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3540 host_impl_
->SetViewportSize(surface_size
);
3543 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3544 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3545 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3546 host_impl_
->ScrollEnd();
3547 EXPECT_TRUE(did_request_redraw_
);
3548 EXPECT_TRUE(did_request_commit_
);
3551 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3552 gfx::Size
surface_size(10, 10);
3553 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3554 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3555 root
->SetHasRenderSurface(true);
3556 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3557 host_impl_
->SetViewportSize(surface_size
);
3560 // Scroll event is ignored because the input coordinate is outside the layer
3562 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3563 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3564 EXPECT_FALSE(did_request_redraw_
);
3565 EXPECT_FALSE(did_request_commit_
);
3568 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3569 gfx::Size
surface_size(10, 10);
3570 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3571 root
->SetHasRenderSurface(true);
3572 scoped_ptr
<LayerImpl
> child
=
3573 CreateScrollableLayer(2, surface_size
, root
.get());
3574 host_impl_
->SetViewportSize(surface_size
);
3576 gfx::Transform matrix
;
3577 matrix
.RotateAboutXAxis(180.0);
3578 child
->SetTransform(matrix
);
3579 child
->SetDoubleSided(false);
3581 root
->AddChild(child
.Pass());
3582 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3585 // Scroll event is ignored because the scrollable layer is not facing the
3586 // viewer and there is nothing scrollable behind it.
3587 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3588 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3589 EXPECT_FALSE(did_request_redraw_
);
3590 EXPECT_FALSE(did_request_commit_
);
3593 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3594 gfx::Size
surface_size(10, 10);
3595 scoped_ptr
<LayerImpl
> clip_layer
=
3596 LayerImpl::Create(host_impl_
->active_tree(), 3);
3597 scoped_ptr
<LayerImpl
> content_layer
=
3598 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3599 content_layer
->SetShouldScrollOnMainThread(true);
3600 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3602 // Note: we can use the same clip layer for both since both calls to
3603 // CreateScrollableLayer() use the same surface size.
3604 scoped_ptr
<LayerImpl
> scroll_layer
=
3605 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3606 scroll_layer
->AddChild(content_layer
.Pass());
3607 clip_layer
->AddChild(scroll_layer
.Pass());
3608 clip_layer
->SetHasRenderSurface(true);
3610 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3611 host_impl_
->SetViewportSize(surface_size
);
3614 // Scrolling fails because the content layer is asking to be scrolled on the
3616 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3617 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3620 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3621 gfx::Size
viewport_size(10, 10);
3622 float page_scale
= 2.f
;
3624 SetupScrollAndContentsLayers(viewport_size
);
3626 // Setup the layers so that the outer viewport is scrollable.
3627 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3629 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3631 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3634 LayerImpl
* root_scroll
=
3635 host_impl_
->active_tree()->OuterViewportScrollLayer();
3636 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3638 gfx::Vector2d
scroll_delta(0, 10);
3639 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3640 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3641 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3642 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3643 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3644 host_impl_
->ScrollEnd();
3646 // Set new page scale from main thread.
3647 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3649 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3650 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3651 expected_scroll_delta
));
3653 // The scroll range should also have been updated.
3654 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3656 // The page scale delta remains constant because the impl thread did not
3658 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3661 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3662 gfx::Size
viewport_size(10, 10);
3663 float page_scale
= 2.f
;
3665 SetupScrollAndContentsLayers(viewport_size
);
3667 // Setup the layers so that the outer viewport is scrollable.
3668 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3670 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3672 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3675 LayerImpl
* root_scroll
=
3676 host_impl_
->active_tree()->OuterViewportScrollLayer();
3677 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3679 gfx::Vector2d
scroll_delta(0, 10);
3680 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3681 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3682 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3683 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3684 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3685 host_impl_
->ScrollEnd();
3687 // Set new page scale on impl thread by pinching.
3688 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3689 host_impl_
->PinchGestureBegin();
3690 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3691 host_impl_
->PinchGestureEnd();
3692 host_impl_
->ScrollEnd();
3695 // The scroll delta is not scaled because the main thread did not scale.
3696 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3697 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3698 expected_scroll_delta
));
3700 // The scroll range should also have been updated.
3701 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3703 // The page scale delta should match the new scale on the impl side.
3704 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3707 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3708 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3709 gfx::Size
surface_size(10, 10);
3710 float default_page_scale
= 1.f
;
3711 gfx::Transform default_page_scale_matrix
;
3712 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3714 float new_page_scale
= 2.f
;
3715 gfx::Transform new_page_scale_matrix
;
3716 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3718 // Create a normal scrollable root layer and another scrollable child layer.
3719 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3720 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3721 LayerImpl
* child
= scroll
->children()[0];
3723 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3724 LayerImpl::Create(host_impl_
->active_tree(), 6);
3725 scoped_ptr
<LayerImpl
> scrollable_child
=
3726 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3727 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3728 child
->AddChild(scrollable_child_clip
.Pass());
3729 LayerImpl
* grand_child
= child
->children()[0];
3731 // Set new page scale on impl thread by pinching.
3732 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3733 host_impl_
->PinchGestureBegin();
3734 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3735 host_impl_
->PinchGestureEnd();
3736 host_impl_
->ScrollEnd();
3739 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3740 // the page scale delta on the root layer is applied hierarchically.
3741 LayerTreeHostImpl::FrameData frame
;
3742 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3743 host_impl_
->DrawLayers(&frame
);
3744 host_impl_
->DidDrawAllLayers(frame
);
3746 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3747 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3748 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3749 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3750 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3751 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3752 EXPECT_EQ(new_page_scale
,
3753 grand_child
->draw_transform().matrix().getDouble(0, 0));
3754 EXPECT_EQ(new_page_scale
,
3755 grand_child
->draw_transform().matrix().getDouble(1, 1));
3758 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3759 gfx::Size
surface_size(30, 30);
3760 SetupScrollAndContentsLayers(surface_size
);
3762 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3764 // Make the outer scroll layer scrollable.
3765 outer_scroll
->SetBounds(gfx::Size(50, 50));
3769 gfx::Vector2d
scroll_delta(0, 10);
3770 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3771 gfx::ScrollOffset
expected_max_scroll(outer_scroll
->MaxScrollOffset());
3772 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3773 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3774 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3775 host_impl_
->ScrollEnd();
3777 float page_scale
= 2.f
;
3778 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3783 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3784 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), outer_scroll
->id(),
3785 expected_scroll_delta
));
3787 // The scroll range should not have changed.
3788 EXPECT_EQ(outer_scroll
->MaxScrollOffset(), expected_max_scroll
);
3790 // The page scale delta remains constant because the impl thread did not
3792 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3795 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
3796 // Scroll a child layer beyond its maximum scroll range and make sure the
3797 // parent layer is scrolled on the axis on which the child was unable to
3799 gfx::Size
surface_size(10, 10);
3800 gfx::Size
content_size(20, 20);
3801 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3802 root
->SetBounds(surface_size
);
3803 root
->SetHasRenderSurface(true);
3804 scoped_ptr
<LayerImpl
> grand_child
=
3805 CreateScrollableLayer(3, content_size
, root
.get());
3807 scoped_ptr
<LayerImpl
> child
=
3808 CreateScrollableLayer(2, content_size
, root
.get());
3809 LayerImpl
* grand_child_layer
= grand_child
.get();
3810 child
->AddChild(grand_child
.Pass());
3812 LayerImpl
* child_layer
= child
.get();
3813 root
->AddChild(child
.Pass());
3814 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3815 host_impl_
->active_tree()->DidBecomeActive();
3816 host_impl_
->SetViewportSize(surface_size
);
3817 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3818 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3822 gfx::Vector2d
scroll_delta(-8, -7);
3823 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3824 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3825 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3826 host_impl_
->ScrollEnd();
3828 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3829 host_impl_
->ProcessScrollDeltas();
3831 // The grand child should have scrolled up to its limit.
3832 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
3833 LayerImpl
* grand_child
= child
->children()[0];
3834 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3835 gfx::Vector2d(0, -5)));
3837 // The child should have only scrolled on the other axis.
3838 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
3839 gfx::Vector2d(-3, 0)));
3843 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
3844 // Scroll a child layer beyond its maximum scroll range and make sure the
3845 // the scroll doesn't bubble up to the parent layer.
3846 gfx::Size
surface_size(20, 20);
3847 gfx::Size
viewport_size(10, 10);
3848 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3849 root
->SetHasRenderSurface(true);
3850 scoped_ptr
<LayerImpl
> root_scrolling
=
3851 CreateScrollableLayer(2, surface_size
, root
.get());
3852 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3854 scoped_ptr
<LayerImpl
> grand_child
=
3855 CreateScrollableLayer(4, surface_size
, root
.get());
3857 scoped_ptr
<LayerImpl
> child
=
3858 CreateScrollableLayer(3, surface_size
, root
.get());
3859 LayerImpl
* grand_child_layer
= grand_child
.get();
3860 child
->AddChild(grand_child
.Pass());
3862 LayerImpl
* child_layer
= child
.get();
3863 root_scrolling
->AddChild(child
.Pass());
3864 root
->AddChild(root_scrolling
.Pass());
3865 EXPECT_EQ(viewport_size
, root
->bounds());
3866 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3867 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3869 host_impl_
->active_tree()->DidBecomeActive();
3870 host_impl_
->SetViewportSize(viewport_size
);
3872 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3873 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3877 gfx::Vector2d
scroll_delta(0, -10);
3878 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3879 host_impl_
->ScrollBegin(gfx::Point(),
3880 InputHandler::NON_BUBBLING_GESTURE
));
3881 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3882 host_impl_
->ScrollEnd();
3884 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3885 host_impl_
->ProcessScrollDeltas();
3887 // The grand child should have scrolled up to its limit.
3889 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
3890 LayerImpl
* grand_child
= child
->children()[0];
3891 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3892 gfx::Vector2d(0, -2)));
3894 // The child should not have scrolled.
3895 ExpectNone(*scroll_info
.get(), child
->id());
3897 // The next time we scroll we should only scroll the parent.
3898 scroll_delta
= gfx::Vector2d(0, -3);
3899 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3900 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3901 InputHandler::NON_BUBBLING_GESTURE
));
3902 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3903 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3904 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
3905 host_impl_
->ScrollEnd();
3907 scroll_info
= host_impl_
->ProcessScrollDeltas();
3909 // The child should have scrolled up to its limit.
3910 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
3911 gfx::Vector2d(0, -3)));
3913 // The grand child should not have scrolled.
3914 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3915 gfx::Vector2d(0, -2)));
3917 // After scrolling the parent, another scroll on the opposite direction
3918 // should still scroll the child.
3919 scroll_delta
= gfx::Vector2d(0, 7);
3920 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3921 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3922 InputHandler::NON_BUBBLING_GESTURE
));
3923 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3924 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3925 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3926 host_impl_
->ScrollEnd();
3928 scroll_info
= host_impl_
->ProcessScrollDeltas();
3930 // The grand child should have scrolled.
3931 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3932 gfx::Vector2d(0, 5)));
3934 // The child should not have scrolled.
3935 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
3936 gfx::Vector2d(0, -3)));
3938 // Scrolling should be adjusted from viewport space.
3939 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
3940 host_impl_
->SetPageScaleOnActiveTree(2.f
);
3942 scroll_delta
= gfx::Vector2d(0, -2);
3943 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3944 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3945 InputHandler::NON_BUBBLING_GESTURE
));
3946 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
3947 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3948 host_impl_
->ScrollEnd();
3950 scroll_info
= host_impl_
->ProcessScrollDeltas();
3952 // Should have scrolled by half the amount in layer space (5 - 2/2)
3953 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3954 gfx::Vector2d(0, 4)));
3957 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
3958 // When we try to scroll a non-scrollable child layer, the scroll delta
3959 // should be applied to one of its ancestors if possible.
3960 gfx::Size
surface_size(10, 10);
3961 gfx::Size
content_size(20, 20);
3962 scoped_ptr
<LayerImpl
> root_clip
=
3963 LayerImpl::Create(host_impl_
->active_tree(), 3);
3964 root_clip
->SetHasRenderSurface(true);
3965 scoped_ptr
<LayerImpl
> root
=
3966 CreateScrollableLayer(1, content_size
, root_clip
.get());
3967 // Make 'root' the clip layer for child: since they have the same sizes the
3968 // child will have zero max_scroll_offset and scrolls will bubble.
3969 scoped_ptr
<LayerImpl
> child
=
3970 CreateScrollableLayer(2, content_size
, root
.get());
3971 child
->SetIsContainerForFixedPositionLayers(true);
3972 root
->SetBounds(content_size
);
3974 int root_scroll_id
= root
->id();
3975 root
->AddChild(child
.Pass());
3976 root_clip
->AddChild(root
.Pass());
3978 host_impl_
->SetViewportSize(surface_size
);
3979 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3980 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
3982 host_impl_
->active_tree()->DidBecomeActive();
3985 gfx::Vector2d
scroll_delta(0, 4);
3986 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3987 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3988 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3989 host_impl_
->ScrollEnd();
3991 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3992 host_impl_
->ProcessScrollDeltas();
3994 // Only the root scroll should have scrolled.
3995 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
3997 ScrollInfoContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
));
4001 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
4002 gfx::Size
surface_size(10, 10);
4003 scoped_ptr
<LayerImpl
> root_clip
=
4004 LayerImpl::Create(host_impl_
->active_tree(), 1);
4005 scoped_ptr
<LayerImpl
> root_scroll
=
4006 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4007 root_scroll
->SetIsContainerForFixedPositionLayers(true);
4008 root_clip
->SetHasRenderSurface(true);
4009 root_clip
->AddChild(root_scroll
.Pass());
4010 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4011 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4013 host_impl_
->active_tree()->DidBecomeActive();
4014 host_impl_
->SetViewportSize(surface_size
);
4016 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4019 host_impl_
->active_tree()->DetachLayerTree();
4020 scoped_ptr
<LayerImpl
> root_clip2
=
4021 LayerImpl::Create(host_impl_
->active_tree(), 3);
4022 scoped_ptr
<LayerImpl
> root_scroll2
=
4023 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
4024 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
4025 root_clip2
->AddChild(root_scroll2
.Pass());
4026 root_clip2
->SetHasRenderSurface(true);
4027 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
4028 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
4030 host_impl_
->active_tree()->DidBecomeActive();
4032 // Scrolling should still work even though we did not draw yet.
4033 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4034 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4037 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
4038 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4040 // Rotate the root layer 90 degrees counter-clockwise about its center.
4041 gfx::Transform rotate_transform
;
4042 rotate_transform
.Rotate(-90.0);
4043 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
4045 gfx::Size
surface_size(50, 50);
4046 host_impl_
->SetViewportSize(surface_size
);
4049 // Scroll to the right in screen coordinates with a gesture.
4050 gfx::Vector2d
gesture_scroll_delta(10, 0);
4051 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4052 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4053 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4054 host_impl_
->ScrollEnd();
4056 // The layer should have scrolled down in its local coordinates.
4057 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4058 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4059 gfx::Vector2d(0, gesture_scroll_delta
.x())));
4061 // Reset and scroll down with the wheel.
4062 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4063 gfx::Vector2d
wheel_scroll_delta(0, 10);
4064 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4065 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4066 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4067 host_impl_
->ScrollEnd();
4069 // The layer should have scrolled down in its local coordinates.
4070 scroll_info
= host_impl_
->ProcessScrollDeltas();
4071 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4072 wheel_scroll_delta
));
4075 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
4076 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4077 int child_clip_layer_id
= 6;
4078 int child_layer_id
= 7;
4079 float child_layer_angle
= -20.f
;
4081 // Create a child layer that is rotated to a non-axis-aligned angle.
4082 scoped_ptr
<LayerImpl
> clip_layer
=
4083 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4084 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4085 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4086 gfx::Transform rotate_transform
;
4087 rotate_transform
.Translate(-50.0, -50.0);
4088 rotate_transform
.Rotate(child_layer_angle
);
4089 rotate_transform
.Translate(50.0, 50.0);
4090 clip_layer
->SetTransform(rotate_transform
);
4092 // Only allow vertical scrolling.
4093 clip_layer
->SetBounds(
4094 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
4095 // The rotation depends on the layer's transform origin, and the child layer
4096 // is a different size than the clip, so make sure the clip layer's origin
4097 // lines up over the child.
4098 clip_layer
->SetTransformOrigin(gfx::Point3F(
4099 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
4100 LayerImpl
* child_ptr
= child
.get();
4101 clip_layer
->AddChild(child
.Pass());
4102 scroll_layer
->AddChild(clip_layer
.Pass());
4104 gfx::Size
surface_size(50, 50);
4105 host_impl_
->SetViewportSize(surface_size
);
4108 // Scroll down in screen coordinates with a gesture.
4109 gfx::Vector2d
gesture_scroll_delta(0, 10);
4110 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4111 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4112 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4113 host_impl_
->ScrollEnd();
4115 // The child layer should have scrolled down in its local coordinates an
4116 // amount proportional to the angle between it and the input scroll delta.
4117 gfx::Vector2d
expected_scroll_delta(
4118 0, gesture_scroll_delta
.y() *
4119 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
4120 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4121 host_impl_
->ProcessScrollDeltas();
4122 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4123 expected_scroll_delta
));
4125 // The root scroll layer should not have scrolled, because the input delta
4126 // was close to the layer's axis of movement.
4127 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4130 // Now reset and scroll the same amount horizontally.
4131 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4132 gfx::Vector2d
gesture_scroll_delta(10, 0);
4133 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4134 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4135 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4136 host_impl_
->ScrollEnd();
4138 // The child layer should have scrolled down in its local coordinates an
4139 // amount proportional to the angle between it and the input scroll delta.
4140 gfx::Vector2d
expected_scroll_delta(
4141 0, -gesture_scroll_delta
.x() *
4142 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
4143 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4144 host_impl_
->ProcessScrollDeltas();
4145 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4146 expected_scroll_delta
));
4148 // The root scroll layer should have scrolled more, since the input scroll
4149 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4150 gfx::Vector2d
expected_root_scroll_delta(
4151 gesture_scroll_delta
.x() *
4152 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
4154 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4155 expected_root_scroll_delta
));
4159 TEST_F(LayerTreeHostImplTest
, ScrollPerspectiveTransformedLayer
) {
4160 // When scrolling an element with perspective, the distance scrolled
4161 // depends on the point at which the scroll begins.
4162 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4163 int child_clip_layer_id
= 6;
4164 int child_layer_id
= 7;
4166 // Create a child layer that is rotated on its x axis, with perspective.
4167 scoped_ptr
<LayerImpl
> clip_layer
=
4168 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4169 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4170 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4171 LayerImpl
* child_ptr
= child
.get();
4172 gfx::Transform perspective_transform
;
4173 perspective_transform
.Translate(-50.0, -50.0);
4174 perspective_transform
.ApplyPerspectiveDepth(20);
4175 perspective_transform
.RotateAboutXAxis(45);
4176 perspective_transform
.Translate(50.0, 50.0);
4177 clip_layer
->SetTransform(perspective_transform
);
4179 clip_layer
->SetBounds(gfx::Size(child_ptr
->bounds().width() / 2,
4180 child_ptr
->bounds().height() / 2));
4181 // The transform depends on the layer's transform origin, and the child layer
4182 // is a different size than the clip, so make sure the clip layer's origin
4183 // lines up over the child.
4184 clip_layer
->SetTransformOrigin(gfx::Point3F(
4185 clip_layer
->bounds().width(), clip_layer
->bounds().height(), 0.f
));
4186 clip_layer
->AddChild(child
.Pass());
4187 scroll_layer
->AddChild(clip_layer
.Pass());
4189 gfx::Size
surface_size(50, 50);
4190 host_impl_
->SetViewportSize(surface_size
);
4192 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
4194 gfx::Vector2d gesture_scroll_deltas
[4];
4195 gesture_scroll_deltas
[0] = gfx::Vector2d(4, 10);
4196 gesture_scroll_deltas
[1] = gfx::Vector2d(4, 10);
4197 gesture_scroll_deltas
[2] = gfx::Vector2d(10, 0);
4198 gesture_scroll_deltas
[3] = gfx::Vector2d(10, 0);
4200 gfx::Vector2d expected_scroll_deltas
[4];
4201 // Perspective affects the vertical delta by a different
4202 // amount depending on the vertical position of the |viewport_point|.
4203 expected_scroll_deltas
[0] = gfx::Vector2d(2, 8);
4204 expected_scroll_deltas
[1] = gfx::Vector2d(1, 4);
4205 // Deltas which start with the same vertical position of the
4206 // |viewport_point| are subject to identical perspective effects.
4207 expected_scroll_deltas
[2] = gfx::Vector2d(4, 0);
4208 expected_scroll_deltas
[3] = gfx::Vector2d(4, 0);
4210 gfx::Point
viewport_point(1, 1);
4212 // Scroll in screen coordinates with a gesture. Each scroll starts
4213 // where the previous scroll ended, but the scroll position is reset
4215 for (int i
= 0; i
< 4; ++i
) {
4216 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4218 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4219 host_impl_
->ScrollBegin(viewport_point
, InputHandler::GESTURE
));
4220 host_impl_
->ScrollBy(viewport_point
, gesture_scroll_deltas
[i
]);
4221 viewport_point
+= gesture_scroll_deltas
[i
];
4222 host_impl_
->ScrollEnd();
4224 scroll_info
= host_impl_
->ProcessScrollDeltas();
4225 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4226 expected_scroll_deltas
[i
]));
4228 // The root scroll layer should not have scrolled, because the input delta
4229 // was close to the layer's axis of movement.
4230 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4234 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
4235 LayerImpl
* scroll_layer
=
4236 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4238 // Scale the layer to twice its normal size.
4240 gfx::Transform scale_transform
;
4241 scale_transform
.Scale(scale
, scale
);
4242 scroll_layer
->SetTransform(scale_transform
);
4244 gfx::Size
surface_size(50, 50);
4245 host_impl_
->SetViewportSize(surface_size
);
4248 // Scroll down in screen coordinates with a gesture.
4249 gfx::Vector2d
scroll_delta(0, 10);
4250 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4251 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4252 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4253 host_impl_
->ScrollEnd();
4255 // The layer should have scrolled down in its local coordinates, but half the
4257 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4258 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4259 gfx::Vector2d(0, scroll_delta
.y() / scale
)));
4261 // Reset and scroll down with the wheel.
4262 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4263 gfx::Vector2d
wheel_scroll_delta(0, 10);
4264 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4265 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4266 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4267 host_impl_
->ScrollEnd();
4269 // It should apply the scale factor to the scroll delta for the wheel event.
4270 scroll_info
= host_impl_
->ProcessScrollDeltas();
4271 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4272 wheel_scroll_delta
));
4275 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
4279 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
4280 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
4281 gfx::Size(width
* scale
- 1, height
* scale
));
4282 host_impl_
->SetDeviceScaleFactor(scale
);
4283 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4285 LayerImpl
* inner_viewport_scroll_layer
=
4286 host_impl_
->active_tree()->InnerViewportScrollLayer();
4287 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4288 inner_viewport_scroll_layer
->MaxScrollOffset());
4291 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
4293 TestScrollOffsetDelegate()
4294 : page_scale_factor_(0.f
),
4295 min_page_scale_factor_(-1.f
),
4296 max_page_scale_factor_(-1.f
),
4297 needs_animate_(false) {}
4299 ~TestScrollOffsetDelegate() override
{}
4301 gfx::ScrollOffset
GetTotalScrollOffset() override
{
4302 return getter_return_value_
;
4305 bool IsExternalScrollActive() const override
{ return false; }
4307 void SetNeedsAnimate(const AnimationCallback
&) override
{
4308 needs_animate_
= true;
4311 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
4312 const gfx::ScrollOffset
& max_scroll_offset
,
4313 const gfx::SizeF
& scrollable_size
,
4314 float page_scale_factor
,
4315 float min_page_scale_factor
,
4316 float max_page_scale_factor
) override
{
4317 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
4318 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
4319 last_set_scroll_offset_
= total_scroll_offset
;
4320 max_scroll_offset_
= max_scroll_offset
;
4321 scrollable_size_
= scrollable_size
;
4322 page_scale_factor_
= page_scale_factor
;
4323 min_page_scale_factor_
= min_page_scale_factor
;
4324 max_page_scale_factor_
= max_page_scale_factor
;
4326 set_getter_return_value(last_set_scroll_offset_
);
4329 bool GetAndResetNeedsAnimate() {
4330 bool needs_animate
= needs_animate_
;
4331 needs_animate_
= false;
4332 return needs_animate
;
4335 gfx::ScrollOffset
last_set_scroll_offset() {
4336 return last_set_scroll_offset_
;
4339 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
4340 getter_return_value_
= value
;
4343 gfx::ScrollOffset
max_scroll_offset() const {
4344 return max_scroll_offset_
;
4347 gfx::SizeF
scrollable_size() const {
4348 return scrollable_size_
;
4351 float page_scale_factor() const {
4352 return page_scale_factor_
;
4355 float min_page_scale_factor() const {
4356 return min_page_scale_factor_
;
4359 float max_page_scale_factor() const {
4360 return max_page_scale_factor_
;
4364 gfx::ScrollOffset last_set_scroll_offset_
;
4365 gfx::ScrollOffset getter_return_value_
;
4366 gfx::ScrollOffset max_scroll_offset_
;
4367 gfx::SizeF scrollable_size_
;
4368 float page_scale_factor_
;
4369 float min_page_scale_factor_
;
4370 float max_page_scale_factor_
;
4371 bool needs_animate_
;
4374 // TODO(jdduke): Test root fling animation.
4375 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4376 TestScrollOffsetDelegate scroll_delegate
;
4377 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4378 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4379 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4380 clip_layer
->SetBounds(gfx::Size(10, 20));
4382 // Setting the delegate results in the current scroll offset being set.
4383 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4384 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4385 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4386 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4387 EXPECT_EQ(initial_scroll_delta
.ToString(),
4388 scroll_delegate
.last_set_scroll_offset().ToString());
4390 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4391 // page_scale_factor and {min|max}_page_scale_factor being set.
4392 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4393 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4394 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4395 EXPECT_EQ(1.f
, scroll_delegate
.min_page_scale_factor());
4396 EXPECT_EQ(1.f
, scroll_delegate
.max_page_scale_factor());
4398 // Updating page scale immediately updates the delegate.
4399 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4400 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4401 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4402 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4403 host_impl_
->SetPageScaleOnActiveTree(2.f
* 1.5f
);
4404 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
4405 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4406 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4407 host_impl_
->SetPageScaleOnActiveTree(2.f
);
4408 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4409 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4410 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4411 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4413 // The pinch gesture doesn't put the delegate into a state where the scroll
4414 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4416 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4417 host_impl_
->PinchGestureBegin();
4418 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4419 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4420 host_impl_
->PinchGestureEnd();
4421 host_impl_
->ScrollEnd();
4423 // Scrolling should be relative to the offset as returned by the delegate.
4424 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4425 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4427 scroll_delegate
.set_getter_return_value(current_offset
);
4428 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4429 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4430 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4432 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4433 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4434 scroll_delegate
.last_set_scroll_offset());
4436 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4437 scroll_delegate
.set_getter_return_value(current_offset
);
4438 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4439 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4440 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4441 scroll_delegate
.last_set_scroll_offset());
4442 host_impl_
->ScrollEnd();
4443 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
4444 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4446 // Forces a full tree synchronization and ensures that the scroll delegate
4447 // sees the correct size of the new tree.
4448 gfx::Size
new_size(42, 24);
4449 host_impl_
->CreatePendingTree();
4450 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
4451 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4452 host_impl_
->ActivateSyncTree();
4453 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4455 // Un-setting the delegate should propagate the delegate's current offset to
4456 // the root scrollable layer.
4457 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4458 scroll_delegate
.set_getter_return_value(current_offset
);
4459 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4460 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4462 EXPECT_EQ(current_offset
.ToString(),
4463 scroll_layer
->CurrentScrollOffset().ToString());
4466 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4467 const gfx::Transform target_space_transform
=
4468 layer
->draw_properties().target_space_transform
;
4469 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4470 gfx::Point translated_point
;
4471 target_space_transform
.TransformPoint(&translated_point
);
4472 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4473 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4476 TEST_F(LayerTreeHostImplTest
,
4477 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4478 TestScrollOffsetDelegate scroll_delegate
;
4479 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4480 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4481 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4482 clip_layer
->SetBounds(gfx::Size(10, 20));
4483 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4485 // Draw first frame to clear any pending draws and check scroll.
4487 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4488 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4490 // Set external scroll delta on delegate and notify LayerTreeHost.
4491 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4492 scroll_delegate
.set_getter_return_value(scroll_offset
);
4493 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4495 // Check scroll delta reflected in layer.
4496 LayerTreeHostImpl::FrameData frame
;
4497 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4498 host_impl_
->DrawLayers(&frame
);
4499 host_impl_
->DidDrawAllLayers(frame
);
4500 EXPECT_FALSE(frame
.has_no_damage
);
4501 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4503 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4506 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4507 InputHandlerScrollResult scroll_result
;
4508 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4509 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4510 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4512 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4514 // In-bounds scrolling does not affect overscroll.
4515 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4516 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4517 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4518 EXPECT_TRUE(scroll_result
.did_scroll
);
4519 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4520 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4521 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4523 // Overscroll events are reflected immediately.
4524 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4525 EXPECT_TRUE(scroll_result
.did_scroll
);
4526 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4527 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4528 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4529 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4530 host_impl_
->accumulated_root_overscroll());
4532 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4533 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4534 EXPECT_TRUE(scroll_result
.did_scroll
);
4535 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4536 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4537 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4538 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4539 host_impl_
->accumulated_root_overscroll());
4541 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4542 EXPECT_FALSE(scroll_result
.did_scroll
);
4543 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4544 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4545 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4546 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4547 host_impl_
->accumulated_root_overscroll());
4549 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4550 EXPECT_TRUE(scroll_result
.did_scroll
);
4551 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4552 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4553 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4554 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4555 host_impl_
->accumulated_root_overscroll());
4557 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4558 EXPECT_TRUE(scroll_result
.did_scroll
);
4559 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4560 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4561 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4562 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4563 host_impl_
->accumulated_root_overscroll());
4565 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4566 EXPECT_TRUE(scroll_result
.did_scroll
);
4567 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4568 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4569 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4570 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4571 host_impl_
->accumulated_root_overscroll());
4573 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4574 EXPECT_TRUE(scroll_result
.did_scroll
);
4575 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4576 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4577 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4578 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4579 host_impl_
->accumulated_root_overscroll());
4581 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4582 // as no scroll occurs.
4583 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4584 EXPECT_FALSE(scroll_result
.did_scroll
);
4585 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4586 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4587 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4588 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4589 host_impl_
->accumulated_root_overscroll());
4591 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4592 EXPECT_FALSE(scroll_result
.did_scroll
);
4593 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4594 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4595 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4596 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4597 host_impl_
->accumulated_root_overscroll());
4599 // Overscroll resets on valid scroll.
4600 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4601 EXPECT_TRUE(scroll_result
.did_scroll
);
4602 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4603 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4604 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4605 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4606 host_impl_
->accumulated_root_overscroll());
4608 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4609 EXPECT_TRUE(scroll_result
.did_scroll
);
4610 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4611 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4612 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4613 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4614 host_impl_
->accumulated_root_overscroll());
4616 host_impl_
->ScrollEnd();
4620 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4621 // Scroll child layers beyond their maximum scroll range and make sure root
4622 // overscroll does not accumulate.
4623 InputHandlerScrollResult scroll_result
;
4624 gfx::Size
surface_size(10, 10);
4625 scoped_ptr
<LayerImpl
> root_clip
=
4626 LayerImpl::Create(host_impl_
->active_tree(), 4);
4627 root_clip
->SetHasRenderSurface(true);
4629 scoped_ptr
<LayerImpl
> root
=
4630 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4632 scoped_ptr
<LayerImpl
> grand_child
=
4633 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4635 scoped_ptr
<LayerImpl
> child
=
4636 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4637 LayerImpl
* grand_child_layer
= grand_child
.get();
4638 child
->AddChild(grand_child
.Pass());
4640 LayerImpl
* child_layer
= child
.get();
4641 root
->AddChild(child
.Pass());
4642 root_clip
->AddChild(root
.Pass());
4643 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4644 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4645 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4646 host_impl_
->active_tree()->DidBecomeActive();
4647 host_impl_
->SetViewportSize(surface_size
);
4650 gfx::Vector2d
scroll_delta(0, -10);
4651 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4652 host_impl_
->ScrollBegin(gfx::Point(),
4653 InputHandler::NON_BUBBLING_GESTURE
));
4654 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4655 EXPECT_TRUE(scroll_result
.did_scroll
);
4656 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4657 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4658 host_impl_
->ScrollEnd();
4660 // The next time we scroll we should only scroll the parent, but overscroll
4661 // should still not reach the root layer.
4662 scroll_delta
= gfx::Vector2d(0, -30);
4663 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4664 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4665 InputHandler::NON_BUBBLING_GESTURE
));
4666 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4667 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4668 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4669 EXPECT_TRUE(scroll_result
.did_scroll
);
4670 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4671 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4672 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4673 host_impl_
->ScrollEnd();
4675 // After scrolling the parent, another scroll on the opposite direction
4676 // should scroll the child.
4677 scroll_delta
= gfx::Vector2d(0, 70);
4678 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4679 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4680 InputHandler::NON_BUBBLING_GESTURE
));
4681 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4682 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4683 EXPECT_TRUE(scroll_result
.did_scroll
);
4684 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4685 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4686 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4687 host_impl_
->ScrollEnd();
4691 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4692 // When we try to scroll a non-scrollable child layer, the scroll delta
4693 // should be applied to one of its ancestors if possible. Overscroll should
4694 // be reflected only when it has bubbled up to the root scrolling layer.
4695 InputHandlerScrollResult scroll_result
;
4696 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4699 gfx::Vector2d
scroll_delta(0, 8);
4700 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4701 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4702 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4703 EXPECT_TRUE(scroll_result
.did_scroll
);
4704 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4705 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4706 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4707 EXPECT_TRUE(scroll_result
.did_scroll
);
4708 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4709 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4710 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4711 EXPECT_FALSE(scroll_result
.did_scroll
);
4712 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4713 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4714 host_impl_
->ScrollEnd();
4718 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4719 InputHandlerScrollResult scroll_result
;
4720 LayerTreeSettings settings
;
4721 CreateHostImpl(settings
, CreateOutputSurface());
4723 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4724 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4725 clip_layer
->SetBounds(gfx::Size(50, 50));
4726 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4727 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4729 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4731 // Even though the layer can't scroll the overscroll still happens.
4732 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4733 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4734 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4735 EXPECT_FALSE(scroll_result
.did_scroll
);
4736 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4737 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4740 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4741 InputHandlerScrollResult scroll_result
;
4742 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4746 // Edge glow effect should be applicable only upon reaching Edges
4747 // of the content. unnecessary glow effect calls shouldn't be
4748 // called while scrolling up without reaching the edge of the content.
4749 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4750 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4751 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4752 EXPECT_TRUE(scroll_result
.did_scroll
);
4753 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4754 EXPECT_EQ(gfx::Vector2dF().ToString(),
4755 host_impl_
->accumulated_root_overscroll().ToString());
4757 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4758 EXPECT_TRUE(scroll_result
.did_scroll
);
4759 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4760 EXPECT_EQ(gfx::Vector2dF().ToString(),
4761 host_impl_
->accumulated_root_overscroll().ToString());
4762 host_impl_
->ScrollEnd();
4763 // unusedrootDelta should be subtracted from applied delta so that
4764 // unwanted glow effect calls are not called.
4765 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4766 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4767 InputHandler::NON_BUBBLING_GESTURE
));
4768 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4769 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4770 EXPECT_TRUE(scroll_result
.did_scroll
);
4771 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4772 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4773 host_impl_
->accumulated_root_overscroll().ToString());
4776 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4777 EXPECT_FALSE(scroll_result
.did_scroll
);
4778 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4779 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4780 host_impl_
->accumulated_root_overscroll().ToString());
4781 host_impl_
->ScrollEnd();
4782 // TestCase to check kEpsilon, which prevents minute values to trigger
4783 // gloweffect without reaching edge.
4784 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4785 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4787 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4788 EXPECT_FALSE(scroll_result
.did_scroll
);
4789 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4790 EXPECT_EQ(gfx::Vector2dF().ToString(),
4791 host_impl_
->accumulated_root_overscroll().ToString());
4792 host_impl_
->ScrollEnd();
4796 class BlendStateCheckLayer
: public LayerImpl
{
4798 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4800 ResourceProvider
* resource_provider
) {
4801 return make_scoped_ptr(
4802 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4805 void AppendQuads(RenderPass
* render_pass
,
4806 AppendQuadsData
* append_quads_data
) override
{
4807 quads_appended_
= true;
4809 gfx::Rect opaque_rect
;
4810 if (contents_opaque())
4811 opaque_rect
= quad_rect_
;
4813 opaque_rect
= opaque_content_rect_
;
4814 gfx::Rect visible_quad_rect
= quad_rect_
;
4816 SharedQuadState
* shared_quad_state
=
4817 render_pass
->CreateAndAppendSharedQuadState();
4818 PopulateSharedQuadState(shared_quad_state
);
4820 TileDrawQuad
* test_blending_draw_quad
=
4821 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
4822 test_blending_draw_quad
->SetNew(shared_quad_state
,
4827 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4831 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
4832 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
4833 EXPECT_EQ(has_render_surface_
, !!render_surface());
4836 void SetExpectation(bool blend
, bool has_render_surface
) {
4838 has_render_surface_
= has_render_surface
;
4839 quads_appended_
= false;
4842 bool quads_appended() const { return quads_appended_
; }
4844 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
4845 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
4846 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
4847 opaque_content_rect_
= rect
;
4851 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
4853 ResourceProvider
* resource_provider
)
4854 : LayerImpl(tree_impl
, id
),
4856 has_render_surface_(false),
4857 quads_appended_(false),
4858 quad_rect_(5, 5, 5, 5),
4859 quad_visible_rect_(5, 5, 5, 5),
4860 resource_id_(resource_provider
->CreateResource(
4863 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
4865 resource_provider
->AllocateForTesting(resource_id_
);
4866 SetBounds(gfx::Size(10, 10));
4867 SetDrawsContent(true);
4871 bool has_render_surface_
;
4872 bool quads_appended_
;
4873 gfx::Rect quad_rect_
;
4874 gfx::Rect opaque_content_rect_
;
4875 gfx::Rect quad_visible_rect_
;
4876 ResourceId resource_id_
;
4879 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
4881 scoped_ptr
<LayerImpl
> root
=
4882 LayerImpl::Create(host_impl_
->active_tree(), 1);
4883 root
->SetBounds(gfx::Size(10, 10));
4884 root
->SetDrawsContent(false);
4885 root
->SetHasRenderSurface(true);
4886 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4888 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4891 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4893 host_impl_
->resource_provider()));
4894 BlendStateCheckLayer
* layer1
=
4895 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
4896 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
4898 LayerTreeHostImpl::FrameData frame
;
4900 // Opaque layer, drawn without blending.
4901 layer1
->SetContentsOpaque(true);
4902 layer1
->SetExpectation(false, false);
4903 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4904 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4905 host_impl_
->DrawLayers(&frame
);
4906 EXPECT_TRUE(layer1
->quads_appended());
4907 host_impl_
->DidDrawAllLayers(frame
);
4909 // Layer with translucent content and painting, so drawn with blending.
4910 layer1
->SetContentsOpaque(false);
4911 layer1
->SetExpectation(true, false);
4912 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4913 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4914 host_impl_
->DrawLayers(&frame
);
4915 EXPECT_TRUE(layer1
->quads_appended());
4916 host_impl_
->DidDrawAllLayers(frame
);
4918 // Layer with translucent opacity, drawn with blending.
4919 layer1
->SetContentsOpaque(true);
4920 layer1
->SetOpacity(0.5f
);
4921 layer1
->SetExpectation(true, false);
4922 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4923 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4924 host_impl_
->DrawLayers(&frame
);
4925 EXPECT_TRUE(layer1
->quads_appended());
4926 host_impl_
->DidDrawAllLayers(frame
);
4928 // Layer with translucent opacity and painting, drawn with blending.
4929 layer1
->SetContentsOpaque(true);
4930 layer1
->SetOpacity(0.5f
);
4931 layer1
->SetExpectation(true, false);
4932 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4933 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4934 host_impl_
->DrawLayers(&frame
);
4935 EXPECT_TRUE(layer1
->quads_appended());
4936 host_impl_
->DidDrawAllLayers(frame
);
4939 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4941 host_impl_
->resource_provider()));
4942 BlendStateCheckLayer
* layer2
=
4943 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
4944 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
4946 // 2 opaque layers, drawn without blending.
4947 layer1
->SetContentsOpaque(true);
4948 layer1
->SetOpacity(1.f
);
4949 layer1
->SetExpectation(false, false);
4950 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4951 layer2
->SetContentsOpaque(true);
4952 layer2
->SetOpacity(1.f
);
4953 layer2
->SetExpectation(false, false);
4954 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4955 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4956 host_impl_
->DrawLayers(&frame
);
4957 EXPECT_TRUE(layer1
->quads_appended());
4958 EXPECT_TRUE(layer2
->quads_appended());
4959 host_impl_
->DidDrawAllLayers(frame
);
4961 // Parent layer with translucent content, drawn with blending.
4962 // Child layer with opaque content, drawn without blending.
4963 layer1
->SetContentsOpaque(false);
4964 layer1
->SetExpectation(true, false);
4965 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4966 layer2
->SetExpectation(false, false);
4967 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4968 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4969 host_impl_
->DrawLayers(&frame
);
4970 EXPECT_TRUE(layer1
->quads_appended());
4971 EXPECT_TRUE(layer2
->quads_appended());
4972 host_impl_
->DidDrawAllLayers(frame
);
4974 // Parent layer with translucent content but opaque painting, drawn without
4976 // Child layer with opaque content, drawn without blending.
4977 layer1
->SetContentsOpaque(true);
4978 layer1
->SetExpectation(false, false);
4979 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4980 layer2
->SetExpectation(false, false);
4981 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4982 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4983 host_impl_
->DrawLayers(&frame
);
4984 EXPECT_TRUE(layer1
->quads_appended());
4985 EXPECT_TRUE(layer2
->quads_appended());
4986 host_impl_
->DidDrawAllLayers(frame
);
4988 // Parent layer with translucent opacity and opaque content. Since it has a
4989 // drawing child, it's drawn to a render surface which carries the opacity,
4990 // so it's itself drawn without blending.
4991 // Child layer with opaque content, drawn without blending (parent surface
4992 // carries the inherited opacity).
4993 layer1
->SetContentsOpaque(true);
4994 layer1
->SetOpacity(0.5f
);
4995 layer1
->SetHasRenderSurface(true);
4996 layer1
->SetExpectation(false, true);
4997 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4998 layer2
->SetExpectation(false, false);
4999 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5000 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5001 host_impl_
->active_tree()->root_layer());
5002 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5003 host_impl_
->DrawLayers(&frame
);
5004 EXPECT_TRUE(layer1
->quads_appended());
5005 EXPECT_TRUE(layer2
->quads_appended());
5006 host_impl_
->DidDrawAllLayers(frame
);
5007 layer1
->SetHasRenderSurface(false);
5009 // Draw again, but with child non-opaque, to make sure
5010 // layer1 not culled.
5011 layer1
->SetContentsOpaque(true);
5012 layer1
->SetOpacity(1.f
);
5013 layer1
->SetExpectation(false, false);
5014 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5015 layer2
->SetContentsOpaque(true);
5016 layer2
->SetOpacity(0.5f
);
5017 layer2
->SetExpectation(true, false);
5018 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5019 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5020 host_impl_
->DrawLayers(&frame
);
5021 EXPECT_TRUE(layer1
->quads_appended());
5022 EXPECT_TRUE(layer2
->quads_appended());
5023 host_impl_
->DidDrawAllLayers(frame
);
5025 // A second way of making the child non-opaque.
5026 layer1
->SetContentsOpaque(true);
5027 layer1
->SetOpacity(1.f
);
5028 layer1
->SetExpectation(false, false);
5029 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5030 layer2
->SetContentsOpaque(false);
5031 layer2
->SetOpacity(1.f
);
5032 layer2
->SetExpectation(true, false);
5033 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5034 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5035 host_impl_
->DrawLayers(&frame
);
5036 EXPECT_TRUE(layer1
->quads_appended());
5037 EXPECT_TRUE(layer2
->quads_appended());
5038 host_impl_
->DidDrawAllLayers(frame
);
5040 // And when the layer says its not opaque but is painted opaque, it is not
5042 layer1
->SetContentsOpaque(true);
5043 layer1
->SetOpacity(1.f
);
5044 layer1
->SetExpectation(false, false);
5045 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5046 layer2
->SetContentsOpaque(true);
5047 layer2
->SetOpacity(1.f
);
5048 layer2
->SetExpectation(false, false);
5049 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5050 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5051 host_impl_
->DrawLayers(&frame
);
5052 EXPECT_TRUE(layer1
->quads_appended());
5053 EXPECT_TRUE(layer2
->quads_appended());
5054 host_impl_
->DidDrawAllLayers(frame
);
5056 // Layer with partially opaque contents, drawn with blending.
5057 layer1
->SetContentsOpaque(false);
5058 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5059 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5060 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5061 layer1
->SetExpectation(true, false);
5062 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5063 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5064 host_impl_
->DrawLayers(&frame
);
5065 EXPECT_TRUE(layer1
->quads_appended());
5066 host_impl_
->DidDrawAllLayers(frame
);
5068 // Layer with partially opaque contents partially culled, drawn with blending.
5069 layer1
->SetContentsOpaque(false);
5070 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5071 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5072 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5073 layer1
->SetExpectation(true, false);
5074 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5075 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5076 host_impl_
->DrawLayers(&frame
);
5077 EXPECT_TRUE(layer1
->quads_appended());
5078 host_impl_
->DidDrawAllLayers(frame
);
5080 // Layer with partially opaque contents culled, drawn with blending.
5081 layer1
->SetContentsOpaque(false);
5082 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5083 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5084 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5085 layer1
->SetExpectation(true, false);
5086 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5087 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5088 host_impl_
->DrawLayers(&frame
);
5089 EXPECT_TRUE(layer1
->quads_appended());
5090 host_impl_
->DidDrawAllLayers(frame
);
5092 // Layer with partially opaque contents and translucent contents culled, drawn
5093 // without blending.
5094 layer1
->SetContentsOpaque(false);
5095 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5096 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5097 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5098 layer1
->SetExpectation(false, false);
5099 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5100 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5101 host_impl_
->DrawLayers(&frame
);
5102 EXPECT_TRUE(layer1
->quads_appended());
5103 host_impl_
->DidDrawAllLayers(frame
);
5106 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
5108 LayerTreeHostImplViewportCoveredTest() :
5109 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
5111 did_activate_pending_tree_(false) {}
5113 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
5115 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5117 return FakeOutputSurface::Create3d();
5120 void SetupActiveTreeLayers() {
5121 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
5122 host_impl_
->active_tree()->SetRootLayer(
5123 LayerImpl::Create(host_impl_
->active_tree(), 1));
5124 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
5125 host_impl_
->active_tree()->root_layer()->AddChild(
5126 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5128 host_impl_
->resource_provider()));
5129 child_
= static_cast<BlendStateCheckLayer
*>(
5130 host_impl_
->active_tree()->root_layer()->children()[0]);
5131 child_
->SetExpectation(false, false);
5132 child_
->SetContentsOpaque(true);
5135 // Expect no gutter rects.
5136 void TestLayerCoversFullViewport() {
5137 gfx::Rect
layer_rect(viewport_size_
);
5138 child_
->SetPosition(layer_rect
.origin());
5139 child_
->SetBounds(layer_rect
.size());
5140 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5141 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5143 LayerTreeHostImpl::FrameData frame
;
5144 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5145 ASSERT_EQ(1u, frame
.render_passes
.size());
5147 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5148 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5149 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5151 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5152 host_impl_
->DidDrawAllLayers(frame
);
5155 // Expect fullscreen gutter rect.
5156 void TestEmptyLayer() {
5157 gfx::Rect
layer_rect(0, 0, 0, 0);
5158 child_
->SetPosition(layer_rect
.origin());
5159 child_
->SetBounds(layer_rect
.size());
5160 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5161 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5163 LayerTreeHostImpl::FrameData frame
;
5164 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5165 ASSERT_EQ(1u, frame
.render_passes
.size());
5167 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5168 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5169 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5171 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5172 host_impl_
->DidDrawAllLayers(frame
);
5175 // Expect four surrounding gutter rects.
5176 void TestLayerInMiddleOfViewport() {
5177 gfx::Rect
layer_rect(500, 500, 200, 200);
5178 child_
->SetPosition(layer_rect
.origin());
5179 child_
->SetBounds(layer_rect
.size());
5180 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5181 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5183 LayerTreeHostImpl::FrameData frame
;
5184 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5185 ASSERT_EQ(1u, frame
.render_passes
.size());
5187 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5188 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
5189 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5191 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5192 host_impl_
->DidDrawAllLayers(frame
);
5195 // Expect no gutter rects.
5196 void TestLayerIsLargerThanViewport() {
5197 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
5198 viewport_size_
.height() + 10);
5199 child_
->SetPosition(layer_rect
.origin());
5200 child_
->SetBounds(layer_rect
.size());
5201 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5202 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5204 LayerTreeHostImpl::FrameData frame
;
5205 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5206 ASSERT_EQ(1u, frame
.render_passes
.size());
5208 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5209 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5210 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5212 host_impl_
->DidDrawAllLayers(frame
);
5215 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
5217 void set_gutter_quad_material(DrawQuad::Material material
) {
5218 gutter_quad_material_
= material
;
5220 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
5221 gutter_texture_size_
= gutter_texture_size
;
5225 size_t CountGutterQuads(const QuadList
& quad_list
) {
5226 size_t num_gutter_quads
= 0;
5227 for (const auto& quad
: quad_list
) {
5228 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
5230 return num_gutter_quads
;
5233 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
5234 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5235 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
5238 // Make sure that the texture coordinates match their expectations.
5239 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
5240 for (const auto& quad
: quad_list
) {
5241 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
5243 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
5244 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
5245 gutter_texture_size_
, host_impl_
->device_scale_factor());
5246 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
5247 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
5248 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
5249 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
5251 texture_quad
->uv_bottom_right
.x(),
5252 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
5254 texture_quad
->uv_bottom_right
.y(),
5255 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
5259 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
5260 return gfx::ToRoundedSize(
5261 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
5264 DrawQuad::Material gutter_quad_material_
;
5265 gfx::Size gutter_texture_size_
;
5266 gfx::Size viewport_size_
;
5267 BlendStateCheckLayer
* child_
;
5268 bool did_activate_pending_tree_
;
5271 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
5272 viewport_size_
= gfx::Size(1000, 1000);
5274 bool always_draw
= false;
5275 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5277 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5278 SetupActiveTreeLayers();
5279 TestLayerCoversFullViewport();
5281 TestLayerInMiddleOfViewport();
5282 TestLayerIsLargerThanViewport();
5285 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
5286 viewport_size_
= gfx::Size(1000, 1000);
5288 bool always_draw
= false;
5289 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5291 host_impl_
->SetDeviceScaleFactor(2.f
);
5292 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5293 SetupActiveTreeLayers();
5294 TestLayerCoversFullViewport();
5296 TestLayerInMiddleOfViewport();
5297 TestLayerIsLargerThanViewport();
5300 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
5301 viewport_size_
= gfx::Size(1000, 1000);
5303 bool always_draw
= true;
5304 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5306 // Pending tree to force active_tree size invalid. Not used otherwise.
5307 host_impl_
->CreatePendingTree();
5308 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5309 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5311 SetupActiveTreeLayers();
5313 TestLayerInMiddleOfViewport();
5314 TestLayerIsLargerThanViewport();
5317 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5318 viewport_size_
= gfx::Size(1000, 1000);
5320 bool always_draw
= true;
5321 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5323 // Set larger viewport and activate it to active tree.
5324 host_impl_
->CreatePendingTree();
5325 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5326 viewport_size_
.height() + 100);
5327 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5328 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5329 host_impl_
->ActivateSyncTree();
5330 EXPECT_TRUE(did_activate_pending_tree_
);
5331 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5333 // Shrink pending tree viewport without activating.
5334 host_impl_
->CreatePendingTree();
5335 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5336 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5338 SetupActiveTreeLayers();
5340 TestLayerInMiddleOfViewport();
5341 TestLayerIsLargerThanViewport();
5344 class FakeDrawableLayerImpl
: public LayerImpl
{
5346 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5347 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5350 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5351 : LayerImpl(tree_impl
, id
) {}
5354 // Only reshape when we know we are going to draw. Otherwise, the reshape
5355 // can leave the window at the wrong size if we never draw and the proper
5356 // viewport size is never set.
5357 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5358 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5359 scoped_ptr
<OutputSurface
> output_surface(
5360 FakeOutputSurface::Create3d(provider
));
5361 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5363 scoped_ptr
<LayerImpl
> root
=
5364 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5365 root
->SetBounds(gfx::Size(10, 10));
5366 root
->SetDrawsContent(true);
5367 root
->SetHasRenderSurface(true);
5368 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5369 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5370 provider
->TestContext3d()->clear_reshape_called();
5372 LayerTreeHostImpl::FrameData frame
;
5373 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5374 host_impl_
->SetDeviceScaleFactor(1.f
);
5375 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5376 host_impl_
->DrawLayers(&frame
);
5377 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5378 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5379 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5380 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5381 host_impl_
->DidDrawAllLayers(frame
);
5382 provider
->TestContext3d()->clear_reshape_called();
5384 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5385 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5386 host_impl_
->DrawLayers(&frame
);
5387 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5388 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5389 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5390 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5391 host_impl_
->DidDrawAllLayers(frame
);
5392 provider
->TestContext3d()->clear_reshape_called();
5394 host_impl_
->SetDeviceScaleFactor(2.f
);
5395 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5396 host_impl_
->DrawLayers(&frame
);
5397 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5398 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5399 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5400 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5401 host_impl_
->DidDrawAllLayers(frame
);
5402 provider
->TestContext3d()->clear_reshape_called();
5405 // Make sure damage tracking propagates all the way to the graphics context,
5406 // where it should request to swap only the sub-buffer that is damaged.
5407 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5408 scoped_refptr
<TestContextProvider
> context_provider(
5409 TestContextProvider::Create());
5410 context_provider
->BindToCurrentThread();
5411 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5413 scoped_ptr
<FakeOutputSurface
> output_surface(
5414 FakeOutputSurface::Create3d(context_provider
));
5415 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5417 // This test creates its own LayerTreeHostImpl, so
5418 // that we can force partial swap enabled.
5419 LayerTreeSettings settings
;
5420 settings
.renderer_settings
.partial_swap_enabled
= true;
5421 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5422 LayerTreeHostImpl::Create(
5423 settings
, this, &proxy_
, &stats_instrumentation_
,
5424 &shared_bitmap_manager_
, NULL
, &task_graph_runner_
, 0);
5425 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5426 layer_tree_host_impl
->WillBeginImplFrame(
5427 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5428 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5430 scoped_ptr
<LayerImpl
> root
=
5431 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5432 root
->SetHasRenderSurface(true);
5433 scoped_ptr
<LayerImpl
> child
=
5434 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5435 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5436 child
->SetBounds(gfx::Size(14, 15));
5437 child
->SetDrawsContent(true);
5438 root
->SetBounds(gfx::Size(500, 500));
5439 root
->SetDrawsContent(true);
5440 root
->AddChild(child
.Pass());
5441 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5443 LayerTreeHostImpl::FrameData frame
;
5445 // First frame, the entire screen should get swapped.
5446 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5447 layer_tree_host_impl
->DrawLayers(&frame
);
5448 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5449 layer_tree_host_impl
->SwapBuffers(frame
);
5450 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5451 EXPECT_EQ(expected_swap_rect
.ToString(),
5452 fake_output_surface
->last_swap_rect().ToString());
5454 // Second frame, only the damaged area should get swapped. Damage should be
5455 // the union of old and new child rects.
5456 // expected damage rect: gfx::Rect(26, 28);
5457 // expected swap rect: vertically flipped, with origin at bottom left corner.
5458 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5460 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5461 layer_tree_host_impl
->DrawLayers(&frame
);
5462 host_impl_
->DidDrawAllLayers(frame
);
5463 layer_tree_host_impl
->SwapBuffers(frame
);
5465 // Make sure that partial swap is constrained to the viewport dimensions
5466 // expected damage rect: gfx::Rect(500, 500);
5467 // expected swap rect: flipped damage rect, but also clamped to viewport
5468 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5469 EXPECT_EQ(expected_swap_rect
.ToString(),
5470 fake_output_surface
->last_swap_rect().ToString());
5472 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5473 // This will damage everything.
5474 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5476 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5477 layer_tree_host_impl
->DrawLayers(&frame
);
5478 host_impl_
->DidDrawAllLayers(frame
);
5479 layer_tree_host_impl
->SwapBuffers(frame
);
5481 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5482 EXPECT_EQ(expected_swap_rect
.ToString(),
5483 fake_output_surface
->last_swap_rect().ToString());
5486 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5487 scoped_ptr
<LayerImpl
> root
=
5488 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5489 scoped_ptr
<LayerImpl
> child
=
5490 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5491 child
->SetBounds(gfx::Size(10, 10));
5492 child
->SetDrawsContent(true);
5493 root
->SetBounds(gfx::Size(10, 10));
5494 root
->SetDrawsContent(true);
5495 root
->SetHasRenderSurface(true);
5496 root
->AddChild(child
.Pass());
5498 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5500 LayerTreeHostImpl::FrameData frame
;
5502 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5503 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5504 EXPECT_EQ(1u, frame
.render_passes
.size());
5505 host_impl_
->DidDrawAllLayers(frame
);
5508 class FakeLayerWithQuads
: public LayerImpl
{
5510 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5511 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5514 void AppendQuads(RenderPass
* render_pass
,
5515 AppendQuadsData
* append_quads_data
) override
{
5516 SharedQuadState
* shared_quad_state
=
5517 render_pass
->CreateAndAppendSharedQuadState();
5518 PopulateSharedQuadState(shared_quad_state
);
5520 SkColor gray
= SkColorSetRGB(100, 100, 100);
5521 gfx::Rect
quad_rect(bounds());
5522 gfx::Rect
visible_quad_rect(quad_rect
);
5523 SolidColorDrawQuad
* my_quad
=
5524 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5526 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5530 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5531 : LayerImpl(tree_impl
, id
) {}
5534 class MockContext
: public TestWebGraphicsContext3D
{
5536 MOCK_METHOD1(useProgram
, void(GLuint program
));
5537 MOCK_METHOD5(uniform4f
, void(GLint location
,
5542 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5544 GLboolean transpose
,
5545 const GLfloat
* value
));
5546 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5550 MOCK_METHOD1(enable
, void(GLenum cap
));
5551 MOCK_METHOD1(disable
, void(GLenum cap
));
5552 MOCK_METHOD4(scissor
, void(GLint x
,
5558 class MockContextHarness
{
5560 MockContext
* context_
;
5563 explicit MockContextHarness(MockContext
* context
)
5564 : context_(context
) {
5565 context_
->set_have_post_sub_buffer(true);
5567 // Catch "uninteresting" calls
5568 EXPECT_CALL(*context_
, useProgram(_
))
5571 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5574 // These are not asserted
5575 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5576 .WillRepeatedly(Return());
5578 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5579 .WillRepeatedly(Return());
5581 // Any un-sanctioned calls to enable() are OK
5582 EXPECT_CALL(*context_
, enable(_
))
5583 .WillRepeatedly(Return());
5585 // Any un-sanctioned calls to disable() are OK
5586 EXPECT_CALL(*context_
, disable(_
))
5587 .WillRepeatedly(Return());
5590 void MustDrawSolidQuad() {
5591 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5593 .RetiresOnSaturation();
5595 EXPECT_CALL(*context_
, useProgram(_
))
5597 .RetiresOnSaturation();
5600 void MustSetScissor(int x
, int y
, int width
, int height
) {
5601 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5602 .WillRepeatedly(Return());
5604 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5606 .WillRepeatedly(Return());
5609 void MustSetNoScissor() {
5610 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5611 .WillRepeatedly(Return());
5613 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5616 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5621 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5622 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5623 MockContext
* mock_context
= mock_context_owned
.get();
5624 MockContextHarness
harness(mock_context
);
5627 LayerTreeSettings settings
= DefaultSettings();
5628 settings
.renderer_settings
.partial_swap_enabled
= false;
5629 CreateHostImpl(settings
,
5630 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5631 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5633 // Without partial swap, and no clipping, no scissor is set.
5634 harness
.MustDrawSolidQuad();
5635 harness
.MustSetNoScissor();
5637 LayerTreeHostImpl::FrameData frame
;
5638 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5639 host_impl_
->DrawLayers(&frame
);
5640 host_impl_
->DidDrawAllLayers(frame
);
5642 Mock::VerifyAndClearExpectations(&mock_context
);
5644 // Without partial swap, but a layer does clip its subtree, one scissor is
5646 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5647 harness
.MustDrawSolidQuad();
5648 harness
.MustSetScissor(0, 0, 10, 10);
5650 LayerTreeHostImpl::FrameData frame
;
5651 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
5652 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5653 host_impl_
->DrawLayers(&frame
);
5654 host_impl_
->DidDrawAllLayers(frame
);
5656 Mock::VerifyAndClearExpectations(&mock_context
);
5659 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5660 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5661 MockContext
* mock_context
= context_owned
.get();
5662 MockContextHarness
harness(mock_context
);
5664 LayerTreeSettings settings
= DefaultSettings();
5665 settings
.renderer_settings
.partial_swap_enabled
= true;
5666 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5667 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5669 // The first frame is not a partially-swapped one. No scissor should be set.
5670 harness
.MustSetNoScissor();
5671 harness
.MustDrawSolidQuad();
5673 LayerTreeHostImpl::FrameData frame
;
5674 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5675 host_impl_
->DrawLayers(&frame
);
5676 host_impl_
->DidDrawAllLayers(frame
);
5678 Mock::VerifyAndClearExpectations(&mock_context
);
5680 // Damage a portion of the frame.
5681 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5682 gfx::Rect(0, 0, 2, 3));
5684 // The second frame will be partially-swapped (the y coordinates are flipped).
5685 harness
.MustSetScissor(0, 7, 2, 3);
5686 harness
.MustDrawSolidQuad();
5688 LayerTreeHostImpl::FrameData frame
;
5689 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5690 host_impl_
->DrawLayers(&frame
);
5691 host_impl_
->DidDrawAllLayers(frame
);
5693 Mock::VerifyAndClearExpectations(&mock_context
);
5696 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5698 LayerTreeHostImplClient
* client
,
5700 SharedBitmapManager
* manager
,
5701 TaskGraphRunner
* task_graph_runner
,
5702 RenderingStatsInstrumentation
* stats_instrumentation
) {
5703 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5704 scoped_ptr
<OutputSurface
> output_surface(
5705 FakeOutputSurface::Create3d(provider
));
5706 provider
->BindToCurrentThread();
5707 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5709 LayerTreeSettings settings
;
5710 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5711 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5712 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
,
5713 manager
, nullptr, task_graph_runner
, 0);
5714 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5715 my_host_impl
->WillBeginImplFrame(
5716 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5717 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5720 Layers are created as follows:
5722 +--------------------+
5726 | | +-------------------+
5728 | | +-------------------+
5733 +--------------------+
5735 Layers 1, 2 have render surfaces
5737 scoped_ptr
<LayerImpl
> root
=
5738 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5739 scoped_ptr
<LayerImpl
> child
=
5740 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5741 scoped_ptr
<LayerImpl
> grand_child
=
5742 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5744 gfx::Rect
root_rect(0, 0, 100, 100);
5745 gfx::Rect
child_rect(10, 10, 50, 50);
5746 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5748 root
->SetHasRenderSurface(true);
5749 root
->SetPosition(root_rect
.origin());
5750 root
->SetBounds(root_rect
.size());
5751 root
->draw_properties().visible_layer_rect
= root_rect
;
5752 root
->SetDrawsContent(false);
5753 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5755 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5756 child
->SetOpacity(0.5f
);
5757 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5758 child
->draw_properties().visible_layer_rect
= child_rect
;
5759 child
->SetDrawsContent(false);
5760 child
->SetHasRenderSurface(true);
5762 grand_child
->SetPosition(grand_child_rect
.origin());
5763 grand_child
->SetBounds(grand_child_rect
.size());
5764 grand_child
->draw_properties().visible_layer_rect
= grand_child_rect
;
5765 grand_child
->SetDrawsContent(true);
5767 child
->AddChild(grand_child
.Pass());
5768 root
->AddChild(child
.Pass());
5770 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5771 return my_host_impl
.Pass();
5774 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5775 TestSharedBitmapManager shared_bitmap_manager
;
5776 TestTaskGraphRunner task_graph_runner
;
5777 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5778 SetupLayersForOpacity(true, this, &proxy_
, &shared_bitmap_manager
,
5779 &task_graph_runner
, &stats_instrumentation_
);
5781 LayerTreeHostImpl::FrameData frame
;
5782 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5784 // Verify all quads have been computed
5785 ASSERT_EQ(2U, frame
.render_passes
.size());
5786 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5787 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5788 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5789 frame
.render_passes
[0]->quad_list
.front()->material
);
5790 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5791 frame
.render_passes
[1]->quad_list
.front()->material
);
5793 my_host_impl
->DrawLayers(&frame
);
5794 my_host_impl
->DidDrawAllLayers(frame
);
5798 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5799 TestSharedBitmapManager shared_bitmap_manager
;
5800 TestTaskGraphRunner task_graph_runner
;
5801 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5802 SetupLayersForOpacity(false, this, &proxy_
, &shared_bitmap_manager
,
5803 &task_graph_runner
, &stats_instrumentation_
);
5805 LayerTreeHostImpl::FrameData frame
;
5806 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5808 // Verify all quads have been computed
5809 ASSERT_EQ(2U, frame
.render_passes
.size());
5810 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5811 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5812 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5813 frame
.render_passes
[0]->quad_list
.front()->material
);
5814 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5815 frame
.render_passes
[1]->quad_list
.front()->material
);
5817 my_host_impl
->DrawLayers(&frame
);
5818 my_host_impl
->DidDrawAllLayers(frame
);
5822 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
5823 scoped_ptr
<TestWebGraphicsContext3D
> context
=
5824 TestWebGraphicsContext3D::Create();
5825 TestWebGraphicsContext3D
* context3d
= context
.get();
5826 scoped_ptr
<OutputSurface
> output_surface(
5827 FakeOutputSurface::Create3d(context
.Pass()));
5828 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5830 scoped_ptr
<LayerImpl
> root_layer
=
5831 LayerImpl::Create(host_impl_
->active_tree(), 1);
5832 root_layer
->SetBounds(gfx::Size(10, 10));
5833 root_layer
->SetHasRenderSurface(true);
5835 scoped_refptr
<VideoFrame
> softwareFrame
=
5836 media::VideoFrame::CreateColorFrame(
5837 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5838 FakeVideoFrameProvider provider
;
5839 provider
.set_frame(softwareFrame
);
5840 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5841 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
5842 video_layer
->SetBounds(gfx::Size(10, 10));
5843 video_layer
->SetDrawsContent(true);
5844 root_layer
->AddChild(video_layer
.Pass());
5846 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
5847 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
5848 io_surface_layer
->SetBounds(gfx::Size(10, 10));
5849 io_surface_layer
->SetDrawsContent(true);
5850 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5851 root_layer
->AddChild(io_surface_layer
.Pass());
5853 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
5855 EXPECT_EQ(0u, context3d
->NumTextures());
5857 LayerTreeHostImpl::FrameData frame
;
5858 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5859 host_impl_
->DrawLayers(&frame
);
5860 host_impl_
->DidDrawAllLayers(frame
);
5861 host_impl_
->SwapBuffers(frame
);
5863 EXPECT_GT(context3d
->NumTextures(), 0u);
5865 // Kill the layer tree.
5866 host_impl_
->active_tree()->SetRootLayer(
5867 LayerImpl::Create(host_impl_
->active_tree(), 100));
5868 // There should be no textures left in use after.
5869 EXPECT_EQ(0u, context3d
->NumTextures());
5872 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
5874 MOCK_METHOD1(useProgram
, void(GLuint program
));
5875 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5881 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
5882 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
5883 new MockDrawQuadsToFillScreenContext
);
5884 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
5887 LayerTreeSettings settings
= DefaultSettings();
5888 settings
.renderer_settings
.partial_swap_enabled
= false;
5889 CreateHostImpl(settings
,
5890 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5891 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
5892 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
5894 // Verify one quad is drawn when transparent background set is not set.
5895 host_impl_
->active_tree()->set_has_transparent_background(false);
5896 EXPECT_CALL(*mock_context
, useProgram(_
))
5898 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
5900 LayerTreeHostImpl::FrameData frame
;
5901 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5902 host_impl_
->DrawLayers(&frame
);
5903 host_impl_
->DidDrawAllLayers(frame
);
5904 Mock::VerifyAndClearExpectations(&mock_context
);
5906 // Verify no quads are drawn when transparent background is set.
5907 host_impl_
->active_tree()->set_has_transparent_background(true);
5908 host_impl_
->SetFullRootLayerDamage();
5909 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5910 host_impl_
->DrawLayers(&frame
);
5911 host_impl_
->DidDrawAllLayers(frame
);
5912 Mock::VerifyAndClearExpectations(&mock_context
);
5915 class LayerTreeHostImplTestWithDelegatingRenderer
5916 : public LayerTreeHostImplTest
{
5918 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
5919 return FakeOutputSurface::CreateDelegating3d();
5922 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
5923 bool expect_to_draw
= !expected_damage
.IsEmpty();
5925 LayerTreeHostImpl::FrameData frame
;
5926 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5928 if (!expect_to_draw
) {
5929 // With no damage, we don't draw, and no quads are created.
5930 ASSERT_EQ(0u, frame
.render_passes
.size());
5932 ASSERT_EQ(1u, frame
.render_passes
.size());
5934 // Verify the damage rect for the root render pass.
5935 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
5936 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
5938 // Verify the root and child layers' quads are generated and not being
5940 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
5942 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
5943 gfx::RectF
expected_child_visible_rect(child
->bounds());
5944 EXPECT_EQ(expected_child_visible_rect
,
5945 root_render_pass
->quad_list
.front()->visible_rect
);
5947 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5948 gfx::RectF
expected_root_visible_rect(root
->bounds());
5949 EXPECT_EQ(expected_root_visible_rect
,
5950 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
5953 host_impl_
->DrawLayers(&frame
);
5954 host_impl_
->DidDrawAllLayers(frame
);
5955 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
5959 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
5960 scoped_ptr
<SolidColorLayerImpl
> root
=
5961 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5962 root
->SetPosition(gfx::PointF());
5963 root
->SetBounds(gfx::Size(10, 10));
5964 root
->SetDrawsContent(true);
5965 root
->SetHasRenderSurface(true);
5967 // Child layer is in the bottom right corner.
5968 scoped_ptr
<SolidColorLayerImpl
> child
=
5969 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
5970 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
5971 child
->SetBounds(gfx::Size(1, 1));
5972 child
->SetDrawsContent(true);
5973 root
->AddChild(child
.Pass());
5975 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5977 // Draw a frame. In the first frame, the entire viewport should be damaged.
5978 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
5979 DrawFrameAndTestDamage(full_frame_damage
);
5981 // The second frame has damage that doesn't touch the child layer. Its quads
5982 // should still be generated.
5983 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
5984 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
5985 DrawFrameAndTestDamage(small_damage
);
5987 // The third frame should have no damage, so no quads should be generated.
5988 gfx::Rect no_damage
;
5989 DrawFrameAndTestDamage(no_damage
);
5992 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5993 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5994 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
5995 LayerTreeSettings settings
;
5996 CreateHostImpl(settings
, CreateOutputSurface());
5997 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
6000 class FakeMaskLayerImpl
: public LayerImpl
{
6002 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
6004 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
6007 void GetContentsResourceId(ResourceId
* resource_id
,
6008 gfx::Size
* resource_size
) const override
{
6013 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
6014 : LayerImpl(tree_impl
, id
) {}
6017 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
6019 using GLRenderer::ShouldAntialiasQuad
;
6022 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
6023 // Due to precision issues (especially on Android), sometimes far
6024 // away quads can end up thinking they need AA.
6025 float device_scale_factor
= 4.f
/ 3.f
;
6026 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
6027 gfx::Size
root_size(2000, 1000);
6028 gfx::Size device_viewport_size
=
6029 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
6030 host_impl_
->SetViewportSize(device_viewport_size
);
6032 host_impl_
->CreatePendingTree();
6033 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
6036 scoped_ptr
<LayerImpl
> scoped_root
=
6037 LayerImpl::Create(host_impl_
->pending_tree(), 1);
6038 LayerImpl
* root
= scoped_root
.get();
6039 root
->SetHasRenderSurface(true);
6041 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
6043 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
6044 LayerImpl::Create(host_impl_
->pending_tree(), 2);
6045 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
6046 root
->AddChild(scoped_scrolling_layer
.Pass());
6048 gfx::Size
content_layer_bounds(100000, 100);
6049 gfx::Size
pile_tile_size(3000, 3000);
6050 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
6051 pile_tile_size
, content_layer_bounds
));
6053 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
6054 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
6056 LayerImpl
* content_layer
= scoped_content_layer
.get();
6057 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
6058 content_layer
->SetBounds(content_layer_bounds
);
6059 content_layer
->SetDrawsContent(true);
6061 root
->SetBounds(root_size
);
6063 gfx::ScrollOffset
scroll_offset(100000, 0);
6064 scrolling_layer
->SetScrollClipLayer(root
->id());
6065 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
6067 host_impl_
->ActivateSyncTree();
6069 bool update_lcd_text
= false;
6070 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
6071 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
6073 LayerTreeHostImpl::FrameData frame
;
6074 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6076 ASSERT_EQ(1u, frame
.render_passes
.size());
6077 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
6078 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
6080 bool clipped
= false, force_aa
= false;
6081 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
6082 quad
->shared_quad_state
->quad_to_target_transform
,
6083 gfx::QuadF(quad
->shared_quad_state
->visible_quad_layer_rect
), &clipped
);
6084 EXPECT_FALSE(clipped
);
6086 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6087 device_layer_quad
, clipped
, force_aa
);
6088 EXPECT_FALSE(antialiased
);
6090 host_impl_
->DrawLayers(&frame
);
6091 host_impl_
->DidDrawAllLayers(frame
);
6095 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
6097 CompositorFrameMetadataTest()
6098 : swap_buffers_complete_(0) {}
6100 void DidSwapBuffersCompleteOnImplThread() override
{
6101 swap_buffers_complete_
++;
6104 int swap_buffers_complete_
;
6107 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
6108 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
6110 LayerTreeHostImpl::FrameData frame
;
6111 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6112 host_impl_
->DrawLayers(&frame
);
6113 host_impl_
->DidDrawAllLayers(frame
);
6115 CompositorFrameAck ack
;
6116 host_impl_
->ReclaimResources(&ack
);
6117 host_impl_
->DidSwapBuffersComplete();
6118 EXPECT_EQ(swap_buffers_complete_
, 1);
6121 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
6123 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6125 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
6127 return SoftwareOutputDevice::BeginPaint(damage_rect
);
6129 void EndPaint() override
{
6130 SoftwareOutputDevice::EndPaint();
6134 int frames_began_
, frames_ended_
;
6137 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
6138 // No main thread evictions in resourceless software mode.
6139 set_reduce_memory_result(false);
6140 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
6141 EXPECT_TRUE(CreateHostImpl(
6143 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
6144 host_impl_
->SetViewportSize(gfx::Size(50, 50));
6146 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6148 const gfx::Transform external_transform
;
6149 const gfx::Rect external_viewport
;
6150 const gfx::Rect external_clip
;
6151 const bool resourceless_software_draw
= true;
6152 host_impl_
->SetExternalDrawConstraints(external_transform
,
6157 resourceless_software_draw
);
6159 EXPECT_EQ(0, software_device
->frames_began_
);
6160 EXPECT_EQ(0, software_device
->frames_ended_
);
6164 EXPECT_EQ(1, software_device
->frames_began_
);
6165 EXPECT_EQ(1, software_device
->frames_ended_
);
6167 // Call another API method that is likely to hit nullptr in this mode.
6168 scoped_refptr
<base::trace_event::TracedValue
> state
=
6169 make_scoped_refptr(new base::trace_event::TracedValue());
6170 host_impl_
->ActivationStateAsValueInto(state
.get());
6173 TEST_F(LayerTreeHostImplTest
,
6174 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
6175 set_reduce_memory_result(false);
6176 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6177 FakeOutputSurface::CreateSoftware(
6178 make_scoped_ptr(new CountingSoftwareDevice
))));
6180 const gfx::Transform external_transform
;
6181 const gfx::Rect external_viewport
;
6182 const gfx::Rect external_clip
;
6183 const bool resourceless_software_draw
= true;
6184 host_impl_
->SetExternalDrawConstraints(external_transform
,
6189 resourceless_software_draw
);
6191 // SolidColorLayerImpl will be drawn.
6192 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
6193 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6195 // VideoLayerImpl will not be drawn.
6196 FakeVideoFrameProvider provider
;
6197 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6198 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
6199 video_layer
->SetBounds(gfx::Size(10, 10));
6200 video_layer
->SetDrawsContent(true);
6201 root_layer
->AddChild(video_layer
.Pass());
6202 SetupRootLayerImpl(root_layer
.Pass());
6204 LayerTreeHostImpl::FrameData frame
;
6205 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6206 host_impl_
->DrawLayers(&frame
);
6207 host_impl_
->DidDrawAllLayers(frame
);
6209 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
6210 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
6213 // Checks that we have a non-0 default allocation if we pass a context that
6214 // doesn't support memory management extensions.
6215 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
6216 LayerTreeSettings settings
;
6217 host_impl_
= LayerTreeHostImpl::Create(
6218 settings
, this, &proxy_
, &stats_instrumentation_
, &shared_bitmap_manager_
,
6219 &gpu_memory_buffer_manager_
, &task_graph_runner_
, 0);
6221 scoped_ptr
<OutputSurface
> output_surface(
6222 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6223 host_impl_
->InitializeRenderer(output_surface
.Pass());
6224 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
6227 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6228 ASSERT_TRUE(host_impl_
->active_tree());
6230 // RequiresHighResToDraw is set when new output surface is used.
6231 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6233 host_impl_
->ResetRequiresHighResToDraw();
6235 host_impl_
->SetVisible(false);
6236 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6237 host_impl_
->SetVisible(true);
6238 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6239 host_impl_
->SetVisible(false);
6240 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6242 host_impl_
->ResetRequiresHighResToDraw();
6244 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6245 host_impl_
->SetVisible(true);
6246 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6249 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6250 ASSERT_TRUE(host_impl_
->active_tree());
6251 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6253 // RequiresHighResToDraw is set when new output surface is used.
6254 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6256 host_impl_
->ResetRequiresHighResToDraw();
6258 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6259 host_impl_
->SetHasGpuRasterizationTrigger(false);
6260 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6261 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6262 host_impl_
->SetHasGpuRasterizationTrigger(true);
6263 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6264 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6265 host_impl_
->SetHasGpuRasterizationTrigger(false);
6266 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6267 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6269 host_impl_
->ResetRequiresHighResToDraw();
6271 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6272 host_impl_
->SetHasGpuRasterizationTrigger(true);
6273 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6274 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6277 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6279 void SetUp() override
{
6281 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_
,
6282 &shared_bitmap_manager_
, &task_graph_runner_
);
6283 host_impl_
.reset(fake_host_impl_
);
6284 host_impl_
->InitializeRenderer(CreateOutputSurface());
6285 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6288 FakeLayerTreeHostImpl
* fake_host_impl_
;
6291 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6292 fake_host_impl_
->DidModifyTilePriorities();
6293 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6294 fake_host_impl_
->SetVisible(false);
6295 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6298 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6299 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6300 TestWebGraphicsContext3D::Create();
6301 TestWebGraphicsContext3D
* context3d
= context
.get();
6302 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6303 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6305 EXPECT_EQ(0u, context3d
->NumTextures());
6307 UIResourceId ui_resource_id
= 1;
6308 bool is_opaque
= false;
6309 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6310 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6311 EXPECT_EQ(1u, context3d
->NumTextures());
6312 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6315 // Multiple requests with the same id is allowed. The previous texture is
6317 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6318 EXPECT_EQ(1u, context3d
->NumTextures());
6319 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6321 EXPECT_NE(id1
, id2
);
6323 // Deleting invalid UIResourceId is allowed and does not change state.
6324 host_impl_
->DeleteUIResource(-1);
6325 EXPECT_EQ(1u, context3d
->NumTextures());
6327 // Should return zero for invalid UIResourceId. Number of textures should
6329 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6330 EXPECT_EQ(1u, context3d
->NumTextures());
6332 host_impl_
->DeleteUIResource(ui_resource_id
);
6333 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6334 EXPECT_EQ(0u, context3d
->NumTextures());
6336 // Should not change state for multiple deletion on one UIResourceId
6337 host_impl_
->DeleteUIResource(ui_resource_id
);
6338 EXPECT_EQ(0u, context3d
->NumTextures());
6341 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6342 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6343 TestWebGraphicsContext3D::Create();
6344 TestWebGraphicsContext3D
* context3d
= context
.get();
6345 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6347 EXPECT_EQ(0u, context3d
->NumTextures());
6349 gfx::Size
size(4, 4);
6350 // SkImageInfo has no support for ETC1. The |info| below contains the right
6351 // total pixel size for the bitmap but not the right height and width. The
6352 // correct width/height are passed directly to UIResourceBitmap.
6354 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6355 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6356 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6357 pixel_ref
->setImmutable();
6358 UIResourceBitmap
bitmap(pixel_ref
, size
);
6359 UIResourceId ui_resource_id
= 1;
6360 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6361 EXPECT_EQ(1u, context3d
->NumTextures());
6362 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6366 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6369 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6370 scoped_refptr
<TestContextProvider
> context_provider
=
6371 TestContextProvider::Create();
6373 CreateHostImpl(DefaultSettings(),
6374 FakeOutputSurface::Create3d(context_provider
));
6376 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6378 ScopedPtrVector
<CopyOutputRequest
> requests
;
6379 requests
.push_back(CopyOutputRequest::CreateRequest(
6380 base::Bind(&ShutdownReleasesContext_Callback
)));
6382 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6384 LayerTreeHostImpl::FrameData frame
;
6385 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6386 host_impl_
->DrawLayers(&frame
);
6387 host_impl_
->DidDrawAllLayers(frame
);
6389 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6390 // texture in a texture mailbox.
6391 EXPECT_FALSE(context_provider
->HasOneRef());
6392 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6394 host_impl_
= nullptr;
6396 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6397 // released, and the texture deleted.
6398 EXPECT_TRUE(context_provider
->HasOneRef());
6399 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6402 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6403 // When flinging via touch, only the child should scroll (we should not
6405 gfx::Size
surface_size(10, 10);
6406 gfx::Size
content_size(20, 20);
6407 scoped_ptr
<LayerImpl
> root_clip
=
6408 LayerImpl::Create(host_impl_
->active_tree(), 3);
6409 root_clip
->SetHasRenderSurface(true);
6411 scoped_ptr
<LayerImpl
> root
=
6412 CreateScrollableLayer(1, content_size
, root_clip
.get());
6413 root
->SetIsContainerForFixedPositionLayers(true);
6414 scoped_ptr
<LayerImpl
> child
=
6415 CreateScrollableLayer(2, content_size
, root_clip
.get());
6417 root
->AddChild(child
.Pass());
6418 int root_id
= root
->id();
6419 root_clip
->AddChild(root
.Pass());
6421 host_impl_
->SetViewportSize(surface_size
);
6422 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6423 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6425 host_impl_
->active_tree()->DidBecomeActive();
6428 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6429 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6431 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6433 gfx::Vector2d
scroll_delta(0, 100);
6434 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6435 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6437 host_impl_
->ScrollEnd();
6439 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6440 host_impl_
->ProcessScrollDeltas();
6442 // Only the child should have scrolled.
6443 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6444 ExpectNone(*scroll_info
.get(), root_id
);
6448 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6449 // Scroll a child layer beyond its maximum scroll range and make sure the
6450 // the scroll doesn't bubble up to the parent layer.
6451 gfx::Size
surface_size(10, 10);
6452 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6453 root
->SetHasRenderSurface(true);
6454 scoped_ptr
<LayerImpl
> root_scrolling
=
6455 CreateScrollableLayer(2, surface_size
, root
.get());
6457 scoped_ptr
<LayerImpl
> grand_child
=
6458 CreateScrollableLayer(4, surface_size
, root
.get());
6459 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6461 scoped_ptr
<LayerImpl
> child
=
6462 CreateScrollableLayer(3, surface_size
, root
.get());
6463 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6464 child
->AddChild(grand_child
.Pass());
6466 root_scrolling
->AddChild(child
.Pass());
6467 root
->AddChild(root_scrolling
.Pass());
6468 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6469 host_impl_
->active_tree()->DidBecomeActive();
6470 host_impl_
->SetViewportSize(surface_size
);
6473 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6475 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6476 LayerImpl
* grand_child
= child
->children()[0];
6478 gfx::Vector2d
scroll_delta(0, -2);
6479 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6480 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6481 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6483 // The grand child should have scrolled up to its limit.
6484 scroll_info
= host_impl_
->ProcessScrollDeltas();
6485 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6487 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6488 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6490 // The child should have received the bubbled delta, but the locked
6491 // scrolling layer should remain set as the grand child.
6492 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6493 scroll_info
= host_impl_
->ProcessScrollDeltas();
6494 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6496 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6497 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(), scroll_delta
));
6498 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6500 // The first |ScrollBy| after the fling should re-lock the scrolling
6501 // layer to the first layer that scrolled, which is the child.
6502 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6503 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6504 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6506 // The child should have scrolled up to its limit.
6507 scroll_info
= host_impl_
->ProcessScrollDeltas();
6508 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6510 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6511 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(),
6512 scroll_delta
+ scroll_delta
));
6514 // As the locked layer is at it's limit, no further scrolling can occur.
6515 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6516 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6517 host_impl_
->ScrollEnd();
6521 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6522 // When flinging via wheel, the root should eventually scroll (we should
6524 gfx::Size
surface_size(10, 10);
6525 gfx::Size
content_size(20, 20);
6526 scoped_ptr
<LayerImpl
> root_clip
=
6527 LayerImpl::Create(host_impl_
->active_tree(), 3);
6528 root_clip
->SetHasRenderSurface(true);
6529 scoped_ptr
<LayerImpl
> root_scroll
=
6530 CreateScrollableLayer(1, content_size
, root_clip
.get());
6531 int root_scroll_id
= root_scroll
->id();
6532 scoped_ptr
<LayerImpl
> child
=
6533 CreateScrollableLayer(2, content_size
, root_clip
.get());
6535 root_scroll
->AddChild(child
.Pass());
6536 root_clip
->AddChild(root_scroll
.Pass());
6538 host_impl_
->SetViewportSize(surface_size
);
6539 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6540 host_impl_
->active_tree()->DidBecomeActive();
6543 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6544 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6546 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6548 gfx::Vector2d
scroll_delta(0, 100);
6549 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6550 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6552 host_impl_
->ScrollEnd();
6554 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6555 host_impl_
->ProcessScrollDeltas();
6557 // The root should have scrolled.
6558 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6559 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll_id
,
6560 gfx::Vector2d(0, 10)));
6564 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6565 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6566 // we should return SCROLL_UNKNOWN.
6567 gfx::Size
content_size(100, 100);
6568 SetupScrollAndContentsLayers(content_size
);
6570 int scroll_layer_id
= 2;
6571 LayerImpl
* scroll_layer
=
6572 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6573 scroll_layer
->SetDrawsContent(true);
6575 int page_scale_layer_id
= 5;
6576 LayerImpl
* page_scale_layer
=
6577 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6579 int occluder_layer_id
= 6;
6580 scoped_ptr
<LayerImpl
> occluder_layer
=
6581 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6582 occluder_layer
->SetDrawsContent(true);
6583 occluder_layer
->SetBounds(content_size
);
6584 occluder_layer
->SetPosition(gfx::PointF());
6586 // The parent of the occluder is *above* the scroller.
6587 page_scale_layer
->AddChild(occluder_layer
.Pass());
6591 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6592 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6595 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6596 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6597 // is not the first scroller we encounter when walking up from the layer, we
6598 // should also return SCROLL_UNKNOWN.
6599 gfx::Size
content_size(100, 100);
6600 SetupScrollAndContentsLayers(content_size
);
6602 int scroll_layer_id
= 2;
6603 LayerImpl
* scroll_layer
=
6604 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6605 scroll_layer
->SetDrawsContent(true);
6607 int occluder_layer_id
= 6;
6608 scoped_ptr
<LayerImpl
> occluder_layer
=
6609 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6610 occluder_layer
->SetDrawsContent(true);
6611 occluder_layer
->SetBounds(content_size
);
6612 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6614 int child_scroll_clip_layer_id
= 7;
6615 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6616 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6618 int child_scroll_layer_id
= 8;
6619 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6620 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6622 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6624 child_scroll
->AddChild(occluder_layer
.Pass());
6625 scroll_layer
->AddChild(child_scroll
.Pass());
6629 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6630 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6633 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6634 gfx::Size
content_size(100, 100);
6635 SetupScrollAndContentsLayers(content_size
);
6637 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6639 int scroll_layer_id
= 2;
6640 LayerImpl
* scroll_layer
=
6641 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6643 int child_scroll_layer_id
= 7;
6644 scoped_ptr
<LayerImpl
> child_scroll
=
6645 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6646 child_scroll
->SetDrawsContent(false);
6648 scroll_layer
->AddChild(child_scroll
.Pass());
6652 // We should not have scrolled |child_scroll| even though we technically "hit"
6653 // it. The reason for this is that if the scrolling the scroll would not move
6654 // any layer that is a drawn RSLL member, then we can ignore the hit.
6656 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6657 // started scrolling the inner viewport.
6658 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6659 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6661 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6664 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6665 gfx::Size
content_size(100, 100);
6666 SetupScrollAndContentsLayers(content_size
);
6668 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6669 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6671 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6672 CreateScrollableLayer(7, content_size
, root
);
6673 invisible_scroll_layer
->SetDrawsContent(false);
6675 scoped_ptr
<LayerImpl
> child_layer
=
6676 LayerImpl::Create(host_impl_
->active_tree(), 8);
6677 child_layer
->SetDrawsContent(false);
6679 scoped_ptr
<LayerImpl
> grand_child_layer
=
6680 LayerImpl::Create(host_impl_
->active_tree(), 9);
6681 grand_child_layer
->SetDrawsContent(true);
6682 grand_child_layer
->SetBounds(content_size
);
6683 // Move the grand child so it's not hit by our test point.
6684 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6686 child_layer
->AddChild(grand_child_layer
.Pass());
6687 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6688 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6692 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6693 // a descendant which is a drawn RSLL member.
6694 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6695 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6697 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6700 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6701 // This test case is very similar to the one above with one key difference:
6702 // the invisible scroller has a scroll child that is indeed draw contents.
6703 // If we attempt to initiate a gesture scroll off of the visible scroll child
6704 // we should still start the scroll child.
6705 gfx::Size
content_size(100, 100);
6706 SetupScrollAndContentsLayers(content_size
);
6708 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6710 int scroll_layer_id
= 2;
6711 LayerImpl
* scroll_layer
=
6712 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6714 int scroll_child_id
= 6;
6715 scoped_ptr
<LayerImpl
> scroll_child
=
6716 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6717 scroll_child
->SetDrawsContent(true);
6718 scroll_child
->SetBounds(content_size
);
6719 // Move the scroll child so it's not hit by our test point.
6720 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6722 int invisible_scroll_layer_id
= 7;
6723 scoped_ptr
<LayerImpl
> invisible_scroll
=
6724 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6725 invisible_scroll
->SetDrawsContent(false);
6727 int container_id
= 8;
6728 scoped_ptr
<LayerImpl
> container
=
6729 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6731 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6732 scroll_children
->insert(scroll_child
.get());
6733 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6735 scroll_child
->SetScrollParent(invisible_scroll
.get());
6737 container
->AddChild(invisible_scroll
.Pass());
6738 container
->AddChild(scroll_child
.Pass());
6740 scroll_layer
->AddChild(container
.Pass());
6744 // We should have scrolled |child_scroll| even though it is invisible.
6745 // The reason for this is that if the scrolling the scroll would move a layer
6746 // that is a drawn RSLL member, then we should accept this hit.
6747 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6748 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6750 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6753 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6754 // to CompositorFrameMetadata after SwapBuffers();
6755 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6756 scoped_ptr
<SolidColorLayerImpl
> root
=
6757 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6758 root
->SetPosition(gfx::PointF());
6759 root
->SetBounds(gfx::Size(10, 10));
6760 root
->SetDrawsContent(true);
6761 root
->SetHasRenderSurface(true);
6763 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6765 FakeOutputSurface
* fake_output_surface
=
6766 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6768 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6769 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6770 EXPECT_TRUE(metadata_latency_before
.empty());
6772 ui::LatencyInfo latency_info
;
6773 latency_info
.AddLatencyNumber(
6774 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6775 scoped_ptr
<SwapPromise
> swap_promise(
6776 new LatencyInfoSwapPromise(latency_info
));
6777 host_impl_
->active_tree()->QueueSwapPromise(swap_promise
.Pass());
6778 host_impl_
->SetNeedsRedraw();
6780 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6781 LayerTreeHostImpl::FrameData frame
;
6782 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6783 host_impl_
->DrawLayers(&frame
);
6784 host_impl_
->DidDrawAllLayers(frame
);
6785 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6787 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6788 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6789 EXPECT_EQ(1u, metadata_latency_after
.size());
6790 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6791 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6794 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6795 int root_layer_id
= 1;
6796 scoped_ptr
<SolidColorLayerImpl
> root
=
6797 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6798 root
->SetPosition(gfx::PointF());
6799 root
->SetBounds(gfx::Size(10, 10));
6800 root
->SetDrawsContent(true);
6801 root
->SetHasRenderSurface(true);
6803 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6805 // Ensure the default frame selection bounds are empty.
6806 FakeOutputSurface
* fake_output_surface
=
6807 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6808 const ViewportSelection
& selection_before
=
6809 fake_output_surface
->last_sent_frame().metadata
.selection
;
6810 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
6811 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
6813 // Plumb the layer-local selection bounds.
6814 gfx::PointF
selection_top(5, 0);
6815 gfx::PointF
selection_bottom(5, 5);
6816 LayerSelection selection
;
6817 selection
.start
.type
= SELECTION_BOUND_CENTER
;
6818 selection
.start
.layer_id
= root_layer_id
;
6819 selection
.start
.edge_bottom
= selection_bottom
;
6820 selection
.start
.edge_top
= selection_top
;
6821 selection
.end
= selection
.start
;
6822 host_impl_
->active_tree()->RegisterSelection(selection
);
6824 // Trigger a draw-swap sequence.
6825 host_impl_
->SetNeedsRedraw();
6827 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6828 LayerTreeHostImpl::FrameData frame
;
6829 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6830 host_impl_
->DrawLayers(&frame
);
6831 host_impl_
->DidDrawAllLayers(frame
);
6832 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6834 // Ensure the selection bounds have propagated to the frame metadata.
6835 const ViewportSelection
& selection_after
=
6836 fake_output_surface
->last_sent_frame().metadata
.selection
;
6837 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
6838 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
6839 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
6840 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
6841 EXPECT_TRUE(selection_after
.start
.visible
);
6842 EXPECT_TRUE(selection_after
.start
.visible
);
6845 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
6847 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
6848 LayerTreeHostImpl
* layer_tree_host_impl
,
6849 int* set_needs_commit_count
,
6850 int* set_needs_redraw_count
,
6851 int* forward_to_main_count
)
6852 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
6853 set_needs_commit_count_(set_needs_commit_count
),
6854 set_needs_redraw_count_(set_needs_redraw_count
),
6855 forward_to_main_count_(forward_to_main_count
) {}
6857 ~SimpleSwapPromiseMonitor() override
{}
6859 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
6861 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
6863 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
6864 (*forward_to_main_count_
)++;
6868 int* set_needs_commit_count_
;
6869 int* set_needs_redraw_count_
;
6870 int* forward_to_main_count_
;
6873 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
6874 int set_needs_commit_count
= 0;
6875 int set_needs_redraw_count
= 0;
6876 int forward_to_main_count
= 0;
6879 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6880 new SimpleSwapPromiseMonitor(NULL
,
6882 &set_needs_commit_count
,
6883 &set_needs_redraw_count
,
6884 &forward_to_main_count
));
6885 host_impl_
->SetNeedsRedraw();
6886 EXPECT_EQ(0, set_needs_commit_count
);
6887 EXPECT_EQ(1, set_needs_redraw_count
);
6888 EXPECT_EQ(0, forward_to_main_count
);
6891 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6893 host_impl_
->SetNeedsRedraw();
6894 EXPECT_EQ(0, set_needs_commit_count
);
6895 EXPECT_EQ(1, set_needs_redraw_count
);
6896 EXPECT_EQ(0, forward_to_main_count
);
6899 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6900 new SimpleSwapPromiseMonitor(NULL
,
6902 &set_needs_commit_count
,
6903 &set_needs_redraw_count
,
6904 &forward_to_main_count
));
6905 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
6906 EXPECT_EQ(0, set_needs_commit_count
);
6907 EXPECT_EQ(2, set_needs_redraw_count
);
6908 EXPECT_EQ(0, forward_to_main_count
);
6912 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6913 new SimpleSwapPromiseMonitor(NULL
,
6915 &set_needs_commit_count
,
6916 &set_needs_redraw_count
,
6917 &forward_to_main_count
));
6918 // Empty damage rect won't signal the monitor.
6919 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
6920 EXPECT_EQ(0, set_needs_commit_count
);
6921 EXPECT_EQ(2, set_needs_redraw_count
);
6922 EXPECT_EQ(0, forward_to_main_count
);
6926 set_needs_commit_count
= 0;
6927 set_needs_redraw_count
= 0;
6928 forward_to_main_count
= 0;
6929 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6930 new SimpleSwapPromiseMonitor(NULL
,
6932 &set_needs_commit_count
,
6933 &set_needs_redraw_count
,
6934 &forward_to_main_count
));
6935 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
6937 // Scrolling normally should not trigger any forwarding.
6938 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6939 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6941 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6942 host_impl_
->ScrollEnd();
6944 EXPECT_EQ(0, set_needs_commit_count
);
6945 EXPECT_EQ(1, set_needs_redraw_count
);
6946 EXPECT_EQ(0, forward_to_main_count
);
6948 // Scrolling with a scroll handler should defer the swap to the main
6950 scroll_layer
->SetHaveScrollEventHandlers(true);
6951 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6952 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6954 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6955 host_impl_
->ScrollEnd();
6957 EXPECT_EQ(0, set_needs_commit_count
);
6958 EXPECT_EQ(2, set_needs_redraw_count
);
6959 EXPECT_EQ(1, forward_to_main_count
);
6963 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
6965 void SetUp() override
{
6966 LayerTreeSettings settings
= DefaultSettings();
6967 CreateHostImpl(settings
, CreateOutputSurface());
6968 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
6969 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
6970 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
6974 static const int top_controls_height_
;
6977 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
6979 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
6980 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6981 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6982 host_impl_
->Animate(base::TimeTicks());
6983 EXPECT_FALSE(did_request_redraw_
);
6986 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
6987 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6988 EXPECT_FALSE(did_request_redraw_
);
6989 host_impl_
->CreatePendingTree();
6990 host_impl_
->sync_tree()->set_top_controls_height(100);
6991 host_impl_
->ActivateSyncTree();
6992 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
6995 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6996 TopControlsStayFullyVisibleOnHeightChange
) {
6997 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6998 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7000 host_impl_
->CreatePendingTree();
7001 host_impl_
->sync_tree()->set_top_controls_height(0);
7002 host_impl_
->ActivateSyncTree();
7003 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7005 host_impl_
->CreatePendingTree();
7006 host_impl_
->sync_tree()->set_top_controls_height(50);
7007 host_impl_
->ActivateSyncTree();
7008 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7011 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
7012 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7013 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7014 host_impl_
->DidChangeTopControlsPosition();
7015 EXPECT_TRUE(did_request_animate_
);
7016 EXPECT_TRUE(did_request_redraw_
);
7019 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
7020 InputHandlerScrollResult result
;
7021 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7022 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7023 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7024 BOTH
, SHOWN
, false);
7027 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7028 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7029 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7030 EXPECT_EQ(gfx::Vector2dF().ToString(),
7031 scroll_layer
->CurrentScrollOffset().ToString());
7033 // Scroll just the top controls and verify that the scroll succeeds.
7034 const float residue
= 10;
7035 float offset
= top_controls_height_
- residue
;
7036 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7037 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7038 EXPECT_TRUE(result
.did_scroll
);
7039 EXPECT_FLOAT_EQ(-offset
,
7040 host_impl_
->top_controls_manager()->ControlsTopOffset());
7041 EXPECT_EQ(gfx::Vector2dF().ToString(),
7042 scroll_layer
->CurrentScrollOffset().ToString());
7044 // Scroll across the boundary
7045 const float content_scroll
= 20;
7046 offset
= residue
+ content_scroll
;
7047 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7048 EXPECT_TRUE(result
.did_scroll
);
7049 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7050 EXPECT_EQ(-top_controls_height_
,
7051 host_impl_
->top_controls_manager()->ControlsTopOffset());
7052 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
7053 scroll_layer
->CurrentScrollOffset().ToString());
7055 // Now scroll back to the top of the content
7056 offset
= -content_scroll
;
7057 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7058 EXPECT_TRUE(result
.did_scroll
);
7059 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7060 EXPECT_EQ(-top_controls_height_
,
7061 host_impl_
->top_controls_manager()->ControlsTopOffset());
7062 EXPECT_EQ(gfx::Vector2dF().ToString(),
7063 scroll_layer
->CurrentScrollOffset().ToString());
7065 // And scroll the top controls completely into view
7066 offset
= -top_controls_height_
;
7067 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7068 EXPECT_TRUE(result
.did_scroll
);
7069 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7070 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7071 EXPECT_EQ(gfx::Vector2dF().ToString(),
7072 scroll_layer
->CurrentScrollOffset().ToString());
7074 // And attempt to scroll past the end
7075 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7076 EXPECT_FALSE(result
.did_scroll
);
7077 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, -50));
7078 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7079 EXPECT_EQ(gfx::Vector2dF().ToString(),
7080 scroll_layer
->CurrentScrollOffset().ToString());
7082 host_impl_
->ScrollEnd();
7085 TEST_F(LayerTreeHostImplWithTopControlsTest
, WheelUnhandledByTopControls
) {
7086 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7087 host_impl_
->SetViewportSize(gfx::Size(50, 100));
7088 host_impl_
->active_tree()->set_top_controls_shrink_blink_size(true);
7089 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7093 LayerImpl
* viewport_layer
= host_impl_
->InnerViewportScrollLayer();
7095 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7096 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7097 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7098 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer
->CurrentScrollOffset());
7100 // Wheel scrolls should not affect the top controls, and should pass
7101 // directly through to the viewport.
7102 const float delta
= top_controls_height_
;
7104 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7105 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7106 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
),
7107 viewport_layer
->CurrentScrollOffset());
7110 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7111 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7112 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
* 2),
7113 viewport_layer
->CurrentScrollOffset());
7116 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
7117 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7118 host_impl_
->SetViewportSize(gfx::Size(100, 200));
7119 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7120 BOTH
, SHOWN
, false);
7123 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7124 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7125 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7126 EXPECT_EQ(gfx::Vector2dF().ToString(),
7127 scroll_layer
->CurrentScrollOffset().ToString());
7129 // Scroll the top controls partially.
7130 const float residue
= 35;
7131 float offset
= top_controls_height_
- residue
;
7133 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7134 EXPECT_FLOAT_EQ(-offset
,
7135 host_impl_
->top_controls_manager()->ControlsTopOffset());
7136 EXPECT_EQ(gfx::Vector2dF().ToString(),
7137 scroll_layer
->CurrentScrollOffset().ToString());
7139 did_request_redraw_
= false;
7140 did_request_animate_
= false;
7141 did_request_commit_
= false;
7143 // End the scroll while the controls are still offset from their limit.
7144 host_impl_
->ScrollEnd();
7145 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7146 EXPECT_TRUE(did_request_animate_
);
7147 EXPECT_TRUE(did_request_redraw_
);
7148 EXPECT_FALSE(did_request_commit_
);
7150 // The top controls should properly animate until finished, despite the scroll
7151 // offset being at the origin.
7152 base::TimeTicks animation_time
= base::TimeTicks::Now();
7153 while (did_request_animate_
) {
7154 did_request_redraw_
= false;
7155 did_request_animate_
= false;
7156 did_request_commit_
= false;
7159 host_impl_
->top_controls_manager()->ControlsTopOffset();
7161 animation_time
+= base::TimeDelta::FromMilliseconds(5);
7162 host_impl_
->Animate(animation_time
);
7163 EXPECT_EQ(gfx::Vector2dF().ToString(),
7164 scroll_layer
->CurrentScrollOffset().ToString());
7167 host_impl_
->top_controls_manager()->ControlsTopOffset();
7169 // No commit is needed as the controls are animating the content offset,
7170 // not the scroll offset.
7171 EXPECT_FALSE(did_request_commit_
);
7173 if (new_offset
!= old_offset
)
7174 EXPECT_TRUE(did_request_redraw_
);
7176 if (new_offset
!= 0) {
7177 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
7178 EXPECT_TRUE(did_request_animate_
);
7181 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7184 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
7185 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7186 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7187 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7188 BOTH
, SHOWN
, false);
7189 float initial_scroll_offset
= 50;
7190 scroll_layer
->PushScrollOffsetFromMainThread(
7191 gfx::ScrollOffset(0, initial_scroll_offset
));
7194 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7195 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7196 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7197 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7198 scroll_layer
->CurrentScrollOffset().ToString());
7200 // Scroll the top controls partially.
7201 const float residue
= 15;
7202 float offset
= top_controls_height_
- residue
;
7204 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7205 EXPECT_FLOAT_EQ(-offset
,
7206 host_impl_
->top_controls_manager()->ControlsTopOffset());
7207 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7208 scroll_layer
->CurrentScrollOffset().ToString());
7210 did_request_redraw_
= false;
7211 did_request_animate_
= false;
7212 did_request_commit_
= false;
7214 // End the scroll while the controls are still offset from the limit.
7215 host_impl_
->ScrollEnd();
7216 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7217 EXPECT_TRUE(did_request_animate_
);
7218 EXPECT_TRUE(did_request_redraw_
);
7219 EXPECT_FALSE(did_request_commit_
);
7221 // Animate the top controls to the limit.
7222 base::TimeTicks animation_time
= base::TimeTicks::Now();
7223 while (did_request_animate_
) {
7224 did_request_redraw_
= false;
7225 did_request_animate_
= false;
7226 did_request_commit_
= false;
7229 host_impl_
->top_controls_manager()->ControlsTopOffset();
7231 animation_time
+= base::TimeDelta::FromMilliseconds(5);
7232 host_impl_
->Animate(animation_time
);
7235 host_impl_
->top_controls_manager()->ControlsTopOffset();
7237 if (new_offset
!= old_offset
) {
7238 EXPECT_TRUE(did_request_redraw_
);
7239 EXPECT_TRUE(did_request_commit_
);
7242 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7243 EXPECT_EQ(-top_controls_height_
,
7244 host_impl_
->top_controls_manager()->ControlsTopOffset());
7247 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7248 TopControlsAnimationAfterMainThreadFlingStopped
) {
7249 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7250 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7251 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7253 float initial_scroll_offset
= 50;
7254 scroll_layer
->PushScrollOffsetFromMainThread(
7255 gfx::ScrollOffset(0, initial_scroll_offset
));
7258 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7259 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7260 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7261 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7262 scroll_layer
->CurrentScrollOffset().ToString());
7264 // Scroll the top controls partially.
7265 const float residue
= 15;
7266 float offset
= top_controls_height_
- residue
;
7268 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7269 EXPECT_FLOAT_EQ(-offset
,
7270 host_impl_
->top_controls_manager()->ControlsTopOffset());
7271 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7272 scroll_layer
->CurrentScrollOffset().ToString());
7274 did_request_redraw_
= false;
7275 did_request_animate_
= false;
7276 did_request_commit_
= false;
7278 // End the fling while the controls are still offset from the limit.
7279 host_impl_
->MainThreadHasStoppedFlinging();
7280 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7281 EXPECT_TRUE(did_request_animate_
);
7282 EXPECT_TRUE(did_request_redraw_
);
7283 EXPECT_FALSE(did_request_commit_
);
7285 // Animate the top controls to the limit.
7286 base::TimeTicks animation_time
= base::TimeTicks::Now();
7287 while (did_request_animate_
) {
7288 did_request_redraw_
= false;
7289 did_request_animate_
= false;
7290 did_request_commit_
= false;
7292 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7294 animation_time
+= base::TimeDelta::FromMilliseconds(5);
7295 host_impl_
->Animate(animation_time
);
7297 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7299 if (new_offset
!= old_offset
) {
7300 EXPECT_TRUE(did_request_redraw_
);
7301 EXPECT_TRUE(did_request_commit_
);
7304 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7305 EXPECT_EQ(-top_controls_height_
,
7306 host_impl_
->top_controls_manager()->ControlsTopOffset());
7309 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7310 TopControlsScrollDeltaInOverScroll
) {
7311 // Verifies that the overscroll delta should not have accumulated in
7312 // the top controls if we do a hide and show without releasing finger.
7314 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7315 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7316 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7320 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7321 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7322 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7326 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7327 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7328 EXPECT_EQ(gfx::Vector2dF().ToString(),
7329 scroll_layer
->CurrentScrollOffset().ToString());
7332 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7333 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7334 scroll_layer
->CurrentScrollOffset().ToString());
7337 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7339 // Should have fully scrolled
7340 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7341 scroll_layer
->CurrentScrollOffset().ToString());
7343 float overscrollamount
= 10;
7345 // Overscroll the content
7347 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7349 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7350 scroll_layer
->CurrentScrollOffset().ToString());
7351 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7352 host_impl_
->accumulated_root_overscroll().ToString());
7354 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7356 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7357 scroll_layer
->CurrentScrollOffset().ToString());
7358 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7361 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7362 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7363 scroll_layer
->CurrentScrollOffset().ToString());
7365 // Top controls should be fully visible
7366 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7368 host_impl_
->ScrollEnd();
7371 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7373 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7374 const gfx::Size
& outer_viewport
,
7375 const gfx::Size
& inner_viewport
) {
7376 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7377 const int kOuterViewportClipLayerId
= 6;
7378 const int kOuterViewportScrollLayerId
= 7;
7379 const int kInnerViewportScrollLayerId
= 2;
7380 const int kInnerViewportClipLayerId
= 4;
7381 const int kPageScaleLayerId
= 5;
7383 scoped_ptr
<LayerImpl
> inner_scroll
=
7384 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7385 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7386 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7388 scoped_ptr
<LayerImpl
> inner_clip
=
7389 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7390 inner_clip
->SetBounds(inner_viewport
);
7392 scoped_ptr
<LayerImpl
> page_scale
=
7393 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7395 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7396 inner_scroll
->SetBounds(outer_viewport
);
7397 inner_scroll
->SetPosition(gfx::PointF());
7399 scoped_ptr
<LayerImpl
> outer_clip
=
7400 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7401 outer_clip
->SetBounds(outer_viewport
);
7402 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7404 scoped_ptr
<LayerImpl
> outer_scroll
=
7405 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7406 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7407 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7408 outer_scroll
->SetBounds(content_size
);
7409 outer_scroll
->SetPosition(gfx::PointF());
7411 scoped_ptr
<LayerImpl
> contents
=
7412 LayerImpl::Create(layer_tree_impl
, 8);
7413 contents
->SetDrawsContent(true);
7414 contents
->SetBounds(content_size
);
7415 contents
->SetPosition(gfx::PointF());
7417 outer_scroll
->AddChild(contents
.Pass());
7418 outer_clip
->AddChild(outer_scroll
.Pass());
7419 inner_scroll
->AddChild(outer_clip
.Pass());
7420 page_scale
->AddChild(inner_scroll
.Pass());
7421 inner_clip
->AddChild(page_scale
.Pass());
7423 inner_clip
->SetHasRenderSurface(true);
7424 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7425 layer_tree_impl
->SetViewportLayersFromIds(
7426 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7427 kOuterViewportScrollLayerId
);
7429 host_impl_
->active_tree()->DidBecomeActive();
7433 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7434 gfx::Size content_size
= gfx::Size(100, 160);
7435 gfx::Size outer_viewport
= gfx::Size(50, 80);
7436 gfx::Size inner_viewport
= gfx::Size(25, 40);
7438 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7440 TestScrollOffsetDelegate scroll_delegate
;
7441 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7443 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7444 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7447 gfx::ScrollOffset inner_expected
;
7448 gfx::ScrollOffset outer_expected
;
7449 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7450 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7452 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7454 scroll_delegate
.set_getter_return_value(current_offset
);
7455 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
7456 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7457 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7459 // Outer viewport scrolls first. Then the rest is applied to the inner
7461 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7462 inner_scroll
->CurrentScrollOffset());
7463 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7464 outer_scroll
->CurrentScrollOffset());
7468 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7469 gfx::Size content_size
= gfx::Size(100, 160);
7470 gfx::Size outer_viewport
= gfx::Size(50, 80);
7471 gfx::Size inner_viewport
= gfx::Size(25, 40);
7473 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7475 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7476 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7479 gfx::Vector2dF inner_expected
;
7480 gfx::Vector2dF outer_expected
;
7481 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7482 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7484 // Make sure the fling goes to the outer viewport first
7485 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7486 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7487 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7488 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7489 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7491 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7492 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7493 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7494 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), outer_scroll
);
7496 host_impl_
->ScrollEnd();
7497 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7499 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7500 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7502 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7503 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7504 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7505 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7506 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7507 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7509 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7510 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7511 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7513 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7514 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7515 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7517 host_impl_
->ScrollEnd();
7518 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7520 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7521 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7525 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7526 DiagonalScrollBubblesPerfectlyToInner
) {
7527 gfx::Size content_size
= gfx::Size(100, 160);
7528 gfx::Size outer_viewport
= gfx::Size(50, 80);
7529 gfx::Size inner_viewport
= gfx::Size(25, 40);
7531 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7533 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7534 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7537 gfx::Vector2dF inner_expected
;
7538 gfx::Vector2dF outer_expected
;
7539 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7540 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7542 // Make sure the scroll goes to the outer viewport first.
7543 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7544 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7545 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7546 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7547 InputHandler::GESTURE
));
7549 // Scroll near the edge of the outer viewport.
7550 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7551 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7552 outer_expected
+= scroll_delta
;
7553 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7554 InputHandler::GESTURE
));
7556 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7557 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7559 // Now diagonal scroll across the outer viewport boundary in a single event.
7560 // The entirety of the scroll should be consumed, as bubbling between inner
7561 // and outer viewport layers is perfect.
7562 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7563 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7564 InputHandler::GESTURE
));
7565 outer_expected
+= scroll_delta
;
7566 inner_expected
+= scroll_delta
;
7567 host_impl_
->ScrollEnd();
7568 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7569 gfx::Point(), InputHandler::GESTURE
));
7571 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7572 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7576 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7577 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7578 gfx::Size content_size
= gfx::Size(100, 160);
7579 gfx::Size outer_viewport
= gfx::Size(50, 80);
7580 gfx::Size inner_viewport
= gfx::Size(25, 40);
7582 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7584 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7585 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7587 scoped_ptr
<LayerImpl
> child
=
7588 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7589 LayerImpl
* child_scroll
= child
.get();
7590 outer_scroll
->children()[0]->AddChild(child
.Pass());
7594 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7596 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7597 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7598 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7599 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7600 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7601 InputHandler::GESTURE
));
7603 // The child should have scrolled up to its limit.
7604 scroll_info
= host_impl_
->ProcessScrollDeltas();
7605 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7607 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7608 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7610 // The first |ScrollBy| after the fling should re-lock the scrolling
7611 // layer to the first layer that scrolled, the inner viewport scroll layer.
7612 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7613 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7614 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7615 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7616 InputHandler::GESTURE
));
7618 // The inner viewport should have scrolled up to its limit.
7619 scroll_info
= host_impl_
->ProcessScrollDeltas();
7620 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7622 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7624 ScrollInfoContains(*scroll_info
, inner_scroll
->id(), scroll_delta
));
7626 // As the locked layer is at its limit, no further scrolling can occur.
7627 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7628 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7629 host_impl_
->ScrollEnd();
7630 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7631 gfx::Point(), InputHandler::GESTURE
));
7635 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7636 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest
) {
7637 gfx::Size content_size
= gfx::Size(100, 160);
7638 gfx::Size outer_viewport
= gfx::Size(50, 80);
7639 gfx::Size inner_viewport
= gfx::Size(25, 40);
7641 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7643 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7644 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7646 scoped_ptr
<LayerImpl
> child
=
7647 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7648 LayerImpl
* child_scroll
= child
.get();
7649 outer_scroll
->children()[0]->AddChild(child
.Pass());
7653 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7654 host_impl_
->RootScrollBegin(InputHandler::GESTURE
));
7655 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7656 host_impl_
->ScrollEnd();
7657 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7658 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7659 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7660 host_impl_
->ScrollEnd();
7663 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7665 void SetUp() override
{
7666 LayerTreeSettings settings
= DefaultSettings();
7667 settings
.max_memory_for_prepaint_percentage
= 50;
7668 CreateHostImpl(settings
, CreateOutputSurface());
7672 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7673 // Set up a memory policy and percentages which could cause
7674 // 32-bit integer overflows.
7675 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7677 // Verify implicit limits are calculated correctly with no overflows
7678 host_impl_
->SetMemoryPolicy(mem_policy
);
7679 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7680 300u * 1024u * 1024u);
7681 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7682 150u * 1024u * 1024u);
7685 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7686 const gfx::Size
layer_size(100, 100);
7687 gfx::Transform external_transform
;
7688 const gfx::Rect
external_viewport(layer_size
);
7689 const gfx::Rect
external_clip(layer_size
);
7690 const bool resourceless_software_draw
= false;
7691 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7693 host_impl_
->SetExternalDrawConstraints(external_transform
,
7698 resourceless_software_draw
);
7700 EXPECT_TRANSFORMATION_MATRIX_EQ(
7701 external_transform
, layer
->draw_properties().target_space_transform
);
7703 external_transform
.Translate(20, 20);
7704 host_impl_
->SetExternalDrawConstraints(external_transform
,
7709 resourceless_software_draw
);
7711 EXPECT_TRANSFORMATION_MATRIX_EQ(
7712 external_transform
, layer
->draw_properties().target_space_transform
);
7715 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7716 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7719 base::TimeTicks start_time
=
7720 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7722 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7723 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7725 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7727 host_impl_
->Animate(start_time
);
7728 host_impl_
->UpdateAnimationState(true);
7730 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7732 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(50));
7733 host_impl_
->UpdateAnimationState(true);
7735 float y
= scrolling_layer
->CurrentScrollOffset().y();
7736 EXPECT_TRUE(y
> 1 && y
< 49);
7739 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7740 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7742 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(200));
7743 host_impl_
->UpdateAnimationState(true);
7745 y
= scrolling_layer
->CurrentScrollOffset().y();
7746 EXPECT_TRUE(y
> 50 && y
< 100);
7747 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7749 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(250));
7750 host_impl_
->UpdateAnimationState(true);
7752 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7753 scrolling_layer
->CurrentScrollOffset());
7754 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7757 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
7758 TEST_F(LayerTreeHostImplTimelinesTest
, ScrollAnimated
) {
7759 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7762 base::TimeTicks start_time
=
7763 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7765 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7766 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7768 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7770 host_impl_
->Animate(start_time
);
7771 host_impl_
->UpdateAnimationState(true);
7773 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7775 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(50));
7776 host_impl_
->UpdateAnimationState(true);
7778 float y
= scrolling_layer
->CurrentScrollOffset().y();
7779 EXPECT_TRUE(y
> 1 && y
< 49);
7782 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7783 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7785 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(200));
7786 host_impl_
->UpdateAnimationState(true);
7788 y
= scrolling_layer
->CurrentScrollOffset().y();
7789 EXPECT_TRUE(y
> 50 && y
< 100);
7790 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7792 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(250));
7793 host_impl_
->UpdateAnimationState(true);
7795 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7796 scrolling_layer
->CurrentScrollOffset());
7797 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7800 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
7801 host_impl_
->CreatePendingTree();
7803 Region empty_invalidation
;
7804 scoped_refptr
<RasterSource
> pile_with_tiles(
7805 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7806 gfx::Size(10, 10)));
7808 scoped_ptr
<FakePictureLayerImpl
> layer
=
7809 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
7810 layer
->SetBounds(gfx::Size(10, 10));
7811 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
7812 layer
->SetDrawsContent(true);
7813 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
7814 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
7815 layer
->tilings()->tiling_at(0)->set_resolution(
7816 TileResolution::HIGH_RESOLUTION
);
7817 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
7818 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
7819 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
7820 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
7822 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
7823 host_impl_
->pending_tree()->root_layer());
7825 root_layer
->set_has_valid_tile_priorities(true);
7826 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
7827 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7828 RasterTilePriorityQueue::Type::ALL
);
7829 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
7831 root_layer
->set_has_valid_tile_priorities(false);
7832 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
7833 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7834 RasterTilePriorityQueue::Type::ALL
);
7835 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
7838 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
7839 host_impl_
->CreatePendingTree();
7840 host_impl_
->ActivateSyncTree();
7841 host_impl_
->CreatePendingTree();
7843 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
7845 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
7846 FakePictureLayerImpl::Create(pending_tree
, 10);
7847 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
7848 pending_tree
->SetRootLayer(pending_layer
.Pass());
7849 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
7851 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
7852 pending_tree
->DidBecomeActive();
7853 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7855 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
7856 FakePictureLayerImpl::Create(pending_tree
, 11);
7857 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
7858 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
7859 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
7861 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7862 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
7863 pending_tree
->DidBecomeActive();
7864 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7865 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7867 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
7868 FakePictureLayerImpl::Create(pending_tree
, 12);
7869 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
7870 FakePictureLayerImpl::Create(pending_tree
, 13);
7871 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
7872 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
7873 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
7874 ASSERT_EQ(raw_replica_mask_layer
,
7875 raw_pending_layer
->replica_layer()->mask_layer());
7877 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7878 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7879 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
7880 pending_tree
->DidBecomeActive();
7881 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
7882 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
7883 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
7886 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
7887 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7888 host_impl_
->SetViewportSize(gfx::Size(50, 50));
7891 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
7893 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
7894 float page_scale_factor
= 1.f
;
7896 // The scroll deltas should have the page scale factor applied.
7898 host_impl_
->active_tree()->PushPageScaleFromMainThread(
7899 page_scale_factor
, min_page_scale
, max_page_scale
);
7900 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
7901 scroll_layer
->SetScrollDelta(gfx::Vector2d());
7903 float page_scale_delta
= 2.f
;
7904 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
7905 host_impl_
->PinchGestureBegin();
7906 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
7907 host_impl_
->PinchGestureEnd();
7908 host_impl_
->ScrollEnd();
7910 gfx::Vector2dF
scroll_delta(0, 5);
7911 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7912 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7913 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
7915 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7916 host_impl_
->ScrollEnd();
7917 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7918 scroll_layer
->CurrentScrollOffset());
7922 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
7924 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7925 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
7928 int num_lost_surfaces_
;
7931 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
7932 // Really we just need at least one client notification each time
7933 // we go from having a valid output surface to not having a valid output
7935 EXPECT_EQ(0, num_lost_surfaces_
);
7936 host_impl_
->DidLoseOutputSurface();
7937 EXPECT_EQ(1, num_lost_surfaces_
);
7938 host_impl_
->DidLoseOutputSurface();
7939 EXPECT_LE(1, num_lost_surfaces_
);
7942 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
7943 LayerTreeHostImpl::FrameData frame
;
7944 frame
.render_passes
.push_back(RenderPass::Create());
7945 RenderPass
* pass3
= frame
.render_passes
.back();
7946 frame
.render_passes
.push_back(RenderPass::Create());
7947 RenderPass
* pass2
= frame
.render_passes
.back();
7948 frame
.render_passes
.push_back(RenderPass::Create());
7949 RenderPass
* pass1
= frame
.render_passes
.back();
7951 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7952 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7953 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7955 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7956 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7957 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7959 // Add a quad to each pass so they aren't empty.
7960 SolidColorDrawQuad
* color_quad
;
7961 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7962 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7963 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7964 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7965 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7966 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7968 // pass3 is referenced by pass2.
7969 RenderPassDrawQuad
* rpdq
=
7970 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7971 rpdq
->material
= DrawQuad::RENDER_PASS
;
7972 rpdq
->render_pass_id
= pass3
->id
;
7974 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7975 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7976 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7977 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7978 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7979 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7980 EXPECT_EQ(1u, frame
.render_passes
.size());
7981 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7984 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
7985 LayerTreeHostImpl::FrameData frame
;
7986 frame
.render_passes
.push_back(RenderPass::Create());
7987 RenderPass
* pass3
= frame
.render_passes
.back();
7988 frame
.render_passes
.push_back(RenderPass::Create());
7989 RenderPass
* pass2
= frame
.render_passes
.back();
7990 frame
.render_passes
.push_back(RenderPass::Create());
7991 RenderPass
* pass1
= frame
.render_passes
.back();
7993 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7994 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7995 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7997 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7998 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7999 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8001 // pass1 is not empty, but pass2 and pass3 are.
8002 SolidColorDrawQuad
* color_quad
;
8003 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8004 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8006 // pass3 is referenced by pass2.
8007 RenderPassDrawQuad
* rpdq
=
8008 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8009 rpdq
->material
= DrawQuad::RENDER_PASS
;
8010 rpdq
->render_pass_id
= pass3
->id
;
8012 // pass2 is referenced by pass1.
8013 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8014 rpdq
->material
= DrawQuad::RENDER_PASS
;
8015 rpdq
->render_pass_id
= pass2
->id
;
8017 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8018 // should be removed.
8019 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8020 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8021 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8022 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8023 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8024 EXPECT_EQ(1u, frame
.render_passes
.size());
8025 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8026 // The RenderPassDrawQuad should be removed from pass1.
8027 EXPECT_EQ(1u, pass1
->quad_list
.size());
8028 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
8031 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
8032 LayerTreeHostImpl::FrameData frame
;
8033 frame
.render_passes
.push_back(RenderPass::Create());
8034 RenderPass
* pass3
= frame
.render_passes
.back();
8035 frame
.render_passes
.push_back(RenderPass::Create());
8036 RenderPass
* pass2
= frame
.render_passes
.back();
8037 frame
.render_passes
.push_back(RenderPass::Create());
8038 RenderPass
* pass1
= frame
.render_passes
.back();
8040 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8041 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8042 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8044 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8045 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8046 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8048 // pass3 is referenced by pass2.
8049 RenderPassDrawQuad
* rpdq
=
8050 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8051 rpdq
->material
= DrawQuad::RENDER_PASS
;
8052 rpdq
->render_pass_id
= pass3
->id
;
8054 // pass2 is referenced by pass1.
8055 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8056 rpdq
->material
= DrawQuad::RENDER_PASS
;
8057 rpdq
->render_pass_id
= pass2
->id
;
8059 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8060 // should be removed. Then pass1 is empty too, but it's the root so it should
8062 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8063 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8064 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8065 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8066 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8067 EXPECT_EQ(1u, frame
.render_passes
.size());
8068 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8069 // The RenderPassDrawQuad should be removed from pass1.
8070 EXPECT_EQ(0u, pass1
->quad_list
.size());
8073 class FakeVideoFrameController
: public VideoFrameController
{
8075 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
8076 begin_frame_args_
= args
;
8077 did_draw_frame_
= false;
8080 void DidDrawFrame() override
{ did_draw_frame_
= true; }
8082 const BeginFrameArgs
& begin_frame_args() const { return begin_frame_args_
; }
8084 bool did_draw_frame() const { return did_draw_frame_
; }
8087 BeginFrameArgs begin_frame_args_
;
8088 bool did_draw_frame_
= false;
8091 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
8092 host_impl_
->DidFinishImplFrame();
8094 BeginFrameArgs begin_frame_args
=
8095 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8096 FakeVideoFrameController controller
;
8098 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8099 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8100 host_impl_
->AddVideoFrameController(&controller
);
8101 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8102 host_impl_
->DidFinishImplFrame();
8104 EXPECT_FALSE(controller
.did_draw_frame());
8105 LayerTreeHostImpl::FrameData frame
;
8106 host_impl_
->DidDrawAllLayers(frame
);
8107 EXPECT_TRUE(controller
.did_draw_frame());
8109 controller
.OnBeginFrame(begin_frame_args
);
8110 EXPECT_FALSE(controller
.did_draw_frame());
8111 host_impl_
->RemoveVideoFrameController(&controller
);
8112 host_impl_
->DidDrawAllLayers(frame
);
8113 EXPECT_FALSE(controller
.did_draw_frame());
8116 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
8117 host_impl_
->DidFinishImplFrame();
8119 BeginFrameArgs begin_frame_args
=
8120 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8121 FakeVideoFrameController controller
;
8123 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8124 host_impl_
->DidFinishImplFrame();
8126 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8127 host_impl_
->AddVideoFrameController(&controller
);
8128 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8130 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8131 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8132 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8133 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8135 EXPECT_FALSE(controller
.did_draw_frame());
8136 LayerTreeHostImpl::FrameData frame
;
8137 host_impl_
->DidDrawAllLayers(frame
);
8138 EXPECT_TRUE(controller
.did_draw_frame());
8140 controller
.OnBeginFrame(begin_frame_args
);
8141 EXPECT_FALSE(controller
.did_draw_frame());
8142 host_impl_
->RemoveVideoFrameController(&controller
);
8143 host_impl_
->DidDrawAllLayers(frame
);
8144 EXPECT_FALSE(controller
.did_draw_frame());
8147 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
8148 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8150 host_impl_
->SetHasGpuRasterizationTrigger(true);
8151 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8152 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
8153 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8155 host_impl_
->SetHasGpuRasterizationTrigger(false);
8156 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8157 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
8158 host_impl_
->gpu_rasterization_status());
8159 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8161 host_impl_
->SetHasGpuRasterizationTrigger(true);
8162 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8163 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
8164 host_impl_
->gpu_rasterization_status());
8165 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8166 EXPECT_FALSE(host_impl_
->use_msaa());
8168 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
8169 TestWebGraphicsContext3D::Create();
8170 context_with_msaa
->SetMaxSamples(8);
8172 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
8173 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
8174 EXPECT_TRUE(CreateHostImpl(
8175 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
8176 host_impl_
->SetHasGpuRasterizationTrigger(true);
8177 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8178 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
8179 host_impl_
->gpu_rasterization_status());
8180 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8181 EXPECT_TRUE(host_impl_
->use_msaa());
8183 LayerTreeSettings settings
= DefaultSettings();
8184 settings
.gpu_rasterization_enabled
= false;
8185 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8186 host_impl_
->SetHasGpuRasterizationTrigger(true);
8187 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8188 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
8189 host_impl_
->gpu_rasterization_status());
8190 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8192 settings
.gpu_rasterization_forced
= true;
8193 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8195 host_impl_
->SetHasGpuRasterizationTrigger(false);
8196 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8197 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
8198 host_impl_
->gpu_rasterization_status());
8199 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8202 // A mock output surface which lets us detect calls to ForceReclaimResources.
8203 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
8205 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
8206 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8207 TestContextProvider::Create(), TestContextProvider::Create(), false));
8210 MOCK_METHOD0(ForceReclaimResources
, void());
8213 MockReclaimResourcesOutputSurface(
8214 scoped_refptr
<ContextProvider
> context_provider
,
8215 scoped_refptr
<ContextProvider
> worker_context_provider
,
8216 bool delegated_rendering
)
8217 : FakeOutputSurface(context_provider
,
8218 worker_context_provider
,
8219 delegated_rendering
) {}
8222 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8223 // being reclaimed to block drawing between BeginCommit / Swap. This test
8224 // ensures that BeginCommit triggers ForceReclaimResources. See
8225 // crbug.com/489515.
8226 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
8227 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
8228 MockReclaimResourcesOutputSurface::Create3d());
8229 // Hold an unowned pointer to the output surface to use for mock expectations.
8230 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
8232 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
8233 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
8234 host_impl_
->BeginCommit();