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