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