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 DidPrepareTiles() override
{}
152 void DidCompletePageScaleAnimationOnImplThread() override
{
153 did_complete_page_scale_animation_
= true;
155 void OnDrawForOutputSurface() override
{}
156 void PostFrameTimingEventsOnImplThread(
157 scoped_ptr
<FrameTimingTracker::CompositeTimingSet
> composite_events
,
158 scoped_ptr
<FrameTimingTracker::MainFrameTimingSet
> main_frame_events
)
161 void set_reduce_memory_result(bool reduce_memory_result
) {
162 reduce_memory_result_
= reduce_memory_result
;
165 virtual bool CreateHostImpl(const LayerTreeSettings
& settings
,
166 scoped_ptr
<OutputSurface
> output_surface
) {
167 host_impl_
= LayerTreeHostImpl::Create(
168 settings
, this, &proxy_
, &stats_instrumentation_
,
169 &shared_bitmap_manager_
, &gpu_memory_buffer_manager_
,
170 &task_graph_runner_
, 0);
171 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
172 host_impl_
->SetViewportSize(gfx::Size(10, 10));
173 // Set the BeginFrameArgs so that methods which use it are able to.
174 host_impl_
->WillBeginImplFrame(
175 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
179 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
180 root
->SetPosition(gfx::PointF());
181 root
->SetBounds(gfx::Size(10, 10));
182 root
->SetDrawsContent(true);
183 root
->draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
184 root
->SetHasRenderSurface(true);
185 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
188 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
189 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
190 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
191 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
194 static ::testing::AssertionResult
ScrollInfoContains(
195 const ScrollAndScaleSet
& scroll_info
,
197 const gfx::Vector2d
& scroll_delta
) {
198 int times_encountered
= 0;
200 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
201 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
204 if (scroll_delta
!= scroll_info
.scrolls
[i
].scroll_delta
) {
205 return ::testing::AssertionFailure()
206 << "Expected " << scroll_delta
.ToString() << ", not "
207 << scroll_info
.scrolls
[i
].scroll_delta
.ToString();
212 if (times_encountered
!= 1)
213 return ::testing::AssertionFailure() << "No layer found with id " << id
;
214 return ::testing::AssertionSuccess();
217 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
218 int times_encountered
= 0;
220 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
221 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
226 ASSERT_EQ(0, times_encountered
);
229 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
230 const gfx::Size
& content_size
) {
231 // Create both an inner viewport scroll layer and an outer viewport scroll
232 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
233 // 0x0, so the scrolls will be applied directly to the inner viewport.
234 const int kOuterViewportClipLayerId
= 116;
235 const int kOuterViewportScrollLayerId
= 117;
236 const int kContentLayerId
= 118;
237 const int kInnerViewportScrollLayerId
= 2;
238 const int kInnerViewportClipLayerId
= 4;
239 const int kPageScaleLayerId
= 5;
241 scoped_ptr
<LayerImpl
> root
=
242 LayerImpl::Create(layer_tree_impl
, 1);
243 root
->SetBounds(content_size
);
244 root
->SetPosition(gfx::PointF());
245 root
->SetHasRenderSurface(true);
247 scoped_ptr
<LayerImpl
> inner_scroll
=
248 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
249 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
250 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
252 scoped_ptr
<LayerImpl
> inner_clip
=
253 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
254 inner_clip
->SetBounds(
255 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
257 scoped_ptr
<LayerImpl
> page_scale
=
258 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
260 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
261 inner_scroll
->SetBounds(content_size
);
262 inner_scroll
->SetPosition(gfx::PointF());
264 scoped_ptr
<LayerImpl
> outer_clip
=
265 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
266 outer_clip
->SetBounds(content_size
);
267 outer_clip
->SetIsContainerForFixedPositionLayers(true);
269 scoped_ptr
<LayerImpl
> outer_scroll
=
270 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
271 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
272 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
273 outer_scroll
->SetBounds(content_size
);
274 outer_scroll
->SetPosition(gfx::PointF());
276 scoped_ptr
<LayerImpl
> contents
=
277 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
278 contents
->SetDrawsContent(true);
279 contents
->SetBounds(content_size
);
280 contents
->SetPosition(gfx::PointF());
282 outer_scroll
->AddChild(contents
.Pass());
283 outer_clip
->AddChild(outer_scroll
.Pass());
284 inner_scroll
->AddChild(outer_clip
.Pass());
285 page_scale
->AddChild(inner_scroll
.Pass());
286 inner_clip
->AddChild(page_scale
.Pass());
287 root
->AddChild(inner_clip
.Pass());
289 layer_tree_impl
->SetRootLayer(root
.Pass());
290 layer_tree_impl
->SetViewportLayersFromIds(
291 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
292 kOuterViewportScrollLayerId
);
294 layer_tree_impl
->DidBecomeActive();
295 return layer_tree_impl
->InnerViewportScrollLayer();
298 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
299 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
300 host_impl_
->active_tree(), content_size
);
301 host_impl_
->active_tree()->DidBecomeActive();
305 // Sets up a typical virtual viewport setup with one child content layer.
306 // Returns a pointer to the content layer.
307 LayerImpl
* CreateBasicVirtualViewportLayers(const gfx::Size
& viewport_size
,
308 const gfx::Size
& content_size
) {
309 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
310 // the inner a different size from the outer. We'll reuse its layer
311 // hierarchy but adjust the sizing to our needs.
312 CreateScrollAndContentsLayers(host_impl_
->active_tree(), content_size
);
314 LayerImpl
* content_layer
=
315 host_impl_
->OuterViewportScrollLayer()->children().back();
316 content_layer
->SetBounds(content_size
);
317 host_impl_
->OuterViewportScrollLayer()->SetBounds(content_size
);
319 LayerImpl
* outer_clip
= host_impl_
->OuterViewportScrollLayer()->parent();
320 outer_clip
->SetBounds(viewport_size
);
322 LayerImpl
* inner_clip_layer
=
323 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
324 inner_clip_layer
->SetBounds(viewport_size
);
325 host_impl_
->InnerViewportScrollLayer()->SetBounds(viewport_size
);
327 host_impl_
->SetViewportSize(viewport_size
);
328 host_impl_
->active_tree()->DidBecomeActive();
330 return content_layer
;
333 // TODO(wjmaclean) Add clip-layer pointer to parameters.
334 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
335 const gfx::Size
& size
,
336 LayerImpl
* clip_layer
) {
338 DCHECK(id
!= clip_layer
->id());
339 scoped_ptr
<LayerImpl
> layer
=
340 LayerImpl::Create(host_impl_
->active_tree(), id
);
341 layer
->SetScrollClipLayer(clip_layer
->id());
342 layer
->SetDrawsContent(true);
343 layer
->SetBounds(size
);
344 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
349 LayerTreeHostImpl::FrameData frame
;
350 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
351 host_impl_
->DrawLayers(&frame
);
352 host_impl_
->DidDrawAllLayers(frame
);
355 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
356 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
357 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
358 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
359 float device_scale_factor
);
361 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
362 // Note: It is not possible to disable the renderer once it has been set,
363 // so we do not need to test that disabling the renderer notifies us
364 // that can_draw changed.
365 EXPECT_FALSE(host_impl_
->CanDraw());
366 on_can_draw_state_changed_called_
= false;
368 // Set up the root layer, which allows us to draw.
369 SetupScrollAndContentsLayers(gfx::Size(100, 100));
370 EXPECT_TRUE(host_impl_
->CanDraw());
371 EXPECT_TRUE(on_can_draw_state_changed_called_
);
372 on_can_draw_state_changed_called_
= false;
374 // Toggle the root layer to make sure it toggles can_draw
375 host_impl_
->active_tree()->SetRootLayer(nullptr);
376 EXPECT_FALSE(host_impl_
->CanDraw());
377 EXPECT_TRUE(on_can_draw_state_changed_called_
);
378 on_can_draw_state_changed_called_
= false;
380 SetupScrollAndContentsLayers(gfx::Size(100, 100));
381 EXPECT_TRUE(host_impl_
->CanDraw());
382 EXPECT_TRUE(on_can_draw_state_changed_called_
);
383 on_can_draw_state_changed_called_
= false;
385 // Toggle the device viewport size to make sure it toggles can_draw.
386 host_impl_
->SetViewportSize(gfx::Size());
388 EXPECT_TRUE(host_impl_
->CanDraw());
390 EXPECT_FALSE(host_impl_
->CanDraw());
392 EXPECT_TRUE(on_can_draw_state_changed_called_
);
393 on_can_draw_state_changed_called_
= false;
395 host_impl_
->SetViewportSize(gfx::Size(100, 100));
396 EXPECT_TRUE(host_impl_
->CanDraw());
397 EXPECT_TRUE(on_can_draw_state_changed_called_
);
398 on_can_draw_state_changed_called_
= false;
401 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
404 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
405 return FakeOutputSurface::Create3d();
408 void DrawOneFrame() {
409 LayerTreeHostImpl::FrameData frame_data
;
410 host_impl_
->PrepareToDraw(&frame_data
);
411 host_impl_
->DidDrawAllLayers(frame_data
);
415 DebugScopedSetImplThread always_impl_thread_
;
416 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
418 TestSharedBitmapManager shared_bitmap_manager_
;
419 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
420 TestTaskGraphRunner task_graph_runner_
;
421 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
422 FakeRenderingStatsInstrumentation stats_instrumentation_
;
423 bool on_can_draw_state_changed_called_
;
424 bool did_notify_ready_to_activate_
;
425 bool did_request_commit_
;
426 bool did_request_redraw_
;
427 bool did_request_animate_
;
428 bool did_request_prepare_tiles_
;
429 bool did_complete_page_scale_animation_
;
430 bool reduce_memory_result_
;
431 base::Closure animation_task_
;
432 base::TimeDelta requested_animation_delay_
;
435 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
436 bool always_draw
= false;
437 CheckNotifyCalledIfCanDrawChanged(always_draw
);
440 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
441 CreateHostImpl(DefaultSettings(),
442 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
444 bool always_draw
= true;
445 CheckNotifyCalledIfCanDrawChanged(always_draw
);
448 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
449 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
451 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
452 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
455 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
457 scoped_ptr
<LayerImpl
> root
=
458 LayerImpl::Create(host_impl_
->active_tree(), 1);
459 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
460 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
461 root
->children()[1]->AddChild(
462 LayerImpl::Create(host_impl_
->active_tree(), 4));
463 root
->children()[1]->AddChild(
464 LayerImpl::Create(host_impl_
->active_tree(), 5));
465 root
->children()[1]->children()[0]->AddChild(
466 LayerImpl::Create(host_impl_
->active_tree(), 6));
467 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
469 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
471 ExpectClearedScrollDeltasRecursive(root
);
473 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
475 scroll_info
= host_impl_
->ProcessScrollDeltas();
476 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
477 ExpectClearedScrollDeltasRecursive(root
);
479 scroll_info
= host_impl_
->ProcessScrollDeltas();
480 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
481 ExpectClearedScrollDeltasRecursive(root
);
484 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
485 gfx::ScrollOffset
scroll_offset(20, 30);
486 gfx::Vector2d
scroll_delta(11, -15);
488 scoped_ptr
<LayerImpl
> root_clip
=
489 LayerImpl::Create(host_impl_
->active_tree(), 2);
490 scoped_ptr
<LayerImpl
> root
=
491 LayerImpl::Create(host_impl_
->active_tree(), 1);
492 root_clip
->SetBounds(gfx::Size(10, 10));
493 LayerImpl
* root_layer
= root
.get();
494 root_clip
->AddChild(root
.Pass());
495 root_layer
->SetBounds(gfx::Size(110, 110));
496 root_layer
->SetScrollClipLayer(root_clip
->id());
497 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
498 root_layer
->ScrollBy(scroll_delta
);
499 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
501 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
503 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
505 scroll_info
= host_impl_
->ProcessScrollDeltas();
506 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
507 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(), scroll_delta
));
509 gfx::Vector2d
scroll_delta2(-5, 27);
510 root
->ScrollBy(scroll_delta2
);
511 scroll_info
= host_impl_
->ProcessScrollDeltas();
512 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
513 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
514 scroll_delta
+ scroll_delta2
));
516 root
->ScrollBy(gfx::Vector2d());
517 scroll_info
= host_impl_
->ProcessScrollDeltas();
518 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
519 scroll_delta
+ scroll_delta2
));
522 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
523 SetupScrollAndContentsLayers(gfx::Size(100, 100));
524 host_impl_
->SetViewportSize(gfx::Size(50, 50));
527 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
528 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
529 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
530 InputHandler::WHEEL
));
531 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
532 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
533 InputHandler::WHEEL
));
534 host_impl_
->ScrollEnd();
535 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
536 InputHandler::WHEEL
));
537 EXPECT_TRUE(did_request_redraw_
);
538 EXPECT_TRUE(did_request_commit_
);
541 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
542 SetupScrollAndContentsLayers(gfx::Size(100, 100));
543 host_impl_
->SetViewportSize(gfx::Size(50, 50));
546 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
547 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
548 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
549 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
550 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
551 host_impl_
->ScrollEnd();
552 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
555 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
556 // We should not crash when trying to scroll an empty layer tree.
557 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
558 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
561 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
562 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
563 TestWebGraphicsContext3D::Create();
564 context_owned
->set_context_lost(true);
566 // Initialization will fail.
567 EXPECT_FALSE(CreateHostImpl(
568 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
570 SetupScrollAndContentsLayers(gfx::Size(100, 100));
572 // We should not crash when trying to scroll after the renderer initialization
574 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
575 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
578 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
579 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
580 host_impl_
->SetViewportSize(gfx::Size(50, 50));
583 // We should not crash if the tree is replaced while we are scrolling.
584 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
585 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
586 host_impl_
->active_tree()->DetachLayerTree();
588 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
590 // We should still be scrolling, because the scrolled layer also exists in the
592 gfx::Vector2d
scroll_delta(0, 10);
593 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
594 host_impl_
->ScrollEnd();
595 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
597 ScrollInfoContains(*scroll_info
, scroll_layer
->id(), scroll_delta
));
600 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
601 SetupScrollAndContentsLayers(gfx::Size(100, 100));
602 host_impl_
->SetViewportSize(gfx::Size(50, 50));
604 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
606 // With registered event handlers, wheel scrolls don't necessarily
607 // have to go to the main thread.
608 root
->SetHaveWheelEventHandlers(true);
609 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
610 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
611 host_impl_
->ScrollEnd();
613 // But typically the scroll-blocks-on mode will require them to.
614 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
615 SCROLL_BLOCKS_ON_START_TOUCH
);
616 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
617 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
619 // But gesture scrolls can still be handled.
620 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
621 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
622 host_impl_
->ScrollEnd();
624 // And if the handlers go away, wheel scrolls can again be processed
625 // on impl (despite the scroll-blocks-on mode).
626 root
->SetHaveWheelEventHandlers(false);
627 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
628 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
629 host_impl_
->ScrollEnd();
632 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
633 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
634 host_impl_
->SetViewportSize(gfx::Size(50, 50));
636 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
638 LayerImpl
* child
= 0;
640 scoped_ptr
<LayerImpl
> child_layer
=
641 LayerImpl::Create(host_impl_
->active_tree(), 6);
642 child
= child_layer
.get();
643 child_layer
->SetDrawsContent(true);
644 child_layer
->SetPosition(gfx::PointF(0, 20));
645 child_layer
->SetBounds(gfx::Size(50, 50));
646 scroll
->AddChild(child_layer
.Pass());
649 // Touch handler regions determine whether touch events block scroll.
650 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
651 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
652 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
653 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
654 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
656 // But they don't influence the actual handling of the scroll gestures.
657 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
658 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
659 host_impl_
->ScrollEnd();
661 // It's the union of scroll-blocks-on mode bits across all layers in the
662 // scroll paret chain that matters.
663 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
664 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
665 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
666 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
667 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
670 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
671 SetupScrollAndContentsLayers(gfx::Size(100, 100));
672 host_impl_
->SetViewportSize(gfx::Size(50, 50));
674 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
676 // With registered scroll handlers, scrolls don't generally have to go
677 // to the main thread.
678 root
->SetHaveScrollEventHandlers(true);
679 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
680 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
681 host_impl_
->ScrollEnd();
683 // Even the default scroll blocks on mode doesn't require this.
684 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
685 SCROLL_BLOCKS_ON_START_TOUCH
);
686 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
687 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
688 host_impl_
->ScrollEnd();
690 // But the page can opt in to blocking on scroll event handlers.
691 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
692 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
693 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
695 // GESTURE and WHEEL scrolls behave identically in this regard.
696 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
697 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
699 // And if the handlers go away, scrolls can again be processed on impl
700 // (despite the scroll-blocks-on mode).
701 root
->SetHaveScrollEventHandlers(false);
702 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
703 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
704 host_impl_
->ScrollEnd();
707 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
708 host_impl_
->SetViewportSize(gfx::Size(50, 50));
710 // Create a normal scrollable root layer
711 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
712 LayerImpl
* root_child
= root_scroll
->children()[0];
713 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
716 // Create two child scrollable layers
717 LayerImpl
* child1
= 0;
719 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
720 LayerImpl::Create(host_impl_
->active_tree(), 6);
721 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
722 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
723 child1
= scrollable_child_1
.get();
724 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
725 scrollable_child_1
->SetHaveWheelEventHandlers(true);
726 scrollable_child_1
->SetHaveScrollEventHandlers(true);
727 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
728 root_child
->AddChild(scrollable_child_clip_1
.Pass());
731 LayerImpl
* child2
= 0;
733 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
734 LayerImpl::Create(host_impl_
->active_tree(), 8);
735 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
736 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
737 child2
= scrollable_child_2
.get();
738 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
739 scrollable_child_2
->SetHaveWheelEventHandlers(true);
740 scrollable_child_2
->SetHaveScrollEventHandlers(true);
741 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
742 root_child
->AddChild(scrollable_child_clip_2
.Pass());
745 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
746 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
747 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
748 host_impl_
->ScrollEnd();
749 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
750 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
751 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
753 // But not those that hit only other layers.
754 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
755 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
756 host_impl_
->ScrollEnd();
758 // It's the union of bits set across the scroll ancestor chain that matters.
759 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
760 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
761 host_impl_
->ScrollEnd();
762 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
763 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
764 host_impl_
->ScrollEnd();
765 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
766 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
767 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
768 host_impl_
->ScrollEnd();
769 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
770 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
771 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
772 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
773 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
774 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
775 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
778 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
779 SetupScrollAndContentsLayers(gfx::Size(100, 100));
780 host_impl_
->SetViewportSize(gfx::Size(50, 50));
783 // Ignore the fling since no layer is being scrolled
784 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
786 // Start scrolling a layer
787 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
788 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
790 // Now the fling should go ahead since we've started scrolling a layer
791 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
794 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
795 SetupScrollAndContentsLayers(gfx::Size(100, 100));
796 host_impl_
->SetViewportSize(gfx::Size(50, 50));
799 // Ignore the fling since no layer is being scrolled
800 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
802 // Start scrolling a layer
803 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
804 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
806 // Now the fling should go ahead since we've started scrolling a layer
807 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
810 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
811 SetupScrollAndContentsLayers(gfx::Size(100, 100));
812 host_impl_
->SetViewportSize(gfx::Size(50, 50));
814 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
816 root
->SetShouldScrollOnMainThread(true);
818 // Start scrolling a layer
819 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
820 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
822 // The fling should be ignored since there's no layer being scrolled impl-side
823 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
826 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
827 SetupScrollAndContentsLayers(gfx::Size(100, 100));
828 host_impl_
->SetViewportSize(gfx::Size(50, 50));
830 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
832 root
->SetShouldScrollOnMainThread(true);
834 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
835 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
836 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
837 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
840 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
841 SetupScrollAndContentsLayers(gfx::Size(200, 200));
842 host_impl_
->SetViewportSize(gfx::Size(100, 100));
844 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
845 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
849 // All scroll types inside the non-fast scrollable region should fail.
850 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
851 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
852 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
853 InputHandler::WHEEL
));
854 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
855 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
856 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
857 InputHandler::GESTURE
));
859 // All scroll types outside this region should succeed.
860 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
861 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
862 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
863 InputHandler::GESTURE
));
864 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
865 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
866 InputHandler::GESTURE
));
867 host_impl_
->ScrollEnd();
868 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
869 InputHandler::GESTURE
));
870 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
871 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
872 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
873 InputHandler::GESTURE
));
874 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
875 host_impl_
->ScrollEnd();
876 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
877 InputHandler::GESTURE
));
880 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
881 SetupScrollAndContentsLayers(gfx::Size(200, 200));
882 host_impl_
->SetViewportSize(gfx::Size(100, 100));
884 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
885 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
886 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
890 // This point would fall into the non-fast scrollable region except that we've
891 // moved the layer down by 25 pixels.
892 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
893 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
894 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
895 InputHandler::WHEEL
));
896 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
897 host_impl_
->ScrollEnd();
899 // This point is still inside the non-fast region.
900 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
901 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
904 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
905 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
906 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
907 host_impl_
->SetViewportSize(gfx::Size(50, 50));
910 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
911 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
912 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
913 host_impl_
->ScrollEnd();
914 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
917 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
918 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
919 scroll_layer
->SetHaveScrollEventHandlers(true);
920 host_impl_
->SetViewportSize(gfx::Size(50, 50));
923 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
924 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
925 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
926 host_impl_
->ScrollEnd();
927 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
930 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
931 SetupScrollAndContentsLayers(gfx::Size(200, 200));
932 host_impl_
->SetViewportSize(gfx::Size(100, 100));
936 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
937 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
939 // Trying to scroll to the left/top will not succeed.
941 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
943 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
945 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
947 // Scrolling to the right/bottom will succeed.
949 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
951 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
953 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
955 // Scrolling to left/top will now succeed.
957 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
959 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
961 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
963 // Scrolling diagonally against an edge will succeed.
965 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
967 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
969 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
971 // Trying to scroll more than the available space will also succeed.
973 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
976 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
977 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
978 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
982 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
983 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
985 // Trying to scroll without a vertical scrollbar will fail.
986 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
987 gfx::Point(), SCROLL_FORWARD
));
988 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
989 gfx::Point(), SCROLL_BACKWARD
));
991 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
992 PaintedScrollbarLayerImpl::Create(
993 host_impl_
->active_tree(),
996 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
997 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
998 vertical_scrollbar
.get());
1000 // Trying to scroll with a vertical scrollbar will succeed.
1001 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1002 gfx::Point(), SCROLL_FORWARD
));
1003 EXPECT_FLOAT_EQ(875.f
,
1004 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1005 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1006 gfx::Point(), SCROLL_BACKWARD
));
1009 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1010 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1011 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1013 gfx::Size
overflow_size(400, 400);
1014 ASSERT_EQ(1u, scroll_layer
->children().size());
1015 LayerImpl
* overflow
= scroll_layer
->children()[0];
1016 overflow
->SetBounds(overflow_size
);
1017 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1018 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1019 overflow
->SetPosition(gfx::PointF());
1022 gfx::Point
scroll_position(10, 10);
1024 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1025 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1026 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1027 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1029 gfx::Vector2dF
scroll_delta(10, 10);
1030 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1031 host_impl_
->ScrollEnd();
1032 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1033 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1035 overflow
->set_user_scrollable_horizontal(false);
1037 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1038 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1039 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1040 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1042 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1043 host_impl_
->ScrollEnd();
1044 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1045 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1047 overflow
->set_user_scrollable_vertical(false);
1049 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1050 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1052 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1054 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1055 host_impl_
->ScrollEnd();
1056 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1057 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1060 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1061 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1062 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1065 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1066 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1067 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1069 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1070 float page_scale_factor
= 1.f
;
1072 // The impl-based pinch zoom should adjust the max scroll position.
1074 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1075 page_scale_factor
, min_page_scale
, max_page_scale
);
1076 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1077 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1079 float page_scale_delta
= 2.f
;
1081 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1082 host_impl_
->PinchGestureBegin();
1083 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1084 host_impl_
->PinchGestureEnd();
1085 host_impl_
->ScrollEnd();
1086 EXPECT_FALSE(did_request_animate_
);
1087 EXPECT_TRUE(did_request_redraw_
);
1088 EXPECT_TRUE(did_request_commit_
);
1089 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1091 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1092 host_impl_
->ProcessScrollDeltas();
1093 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1095 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1096 scroll_layer
->MaxScrollOffset().ToString());
1099 // Scrolling after a pinch gesture should always be in local space. The
1100 // scroll deltas have the page scale factor applied.
1102 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1103 page_scale_factor
, min_page_scale
, max_page_scale
);
1104 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1105 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1107 float page_scale_delta
= 2.f
;
1108 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1109 host_impl_
->PinchGestureBegin();
1110 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1111 host_impl_
->PinchGestureEnd();
1112 host_impl_
->ScrollEnd();
1114 gfx::Vector2d
scroll_delta(0, 10);
1115 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1116 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1117 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1118 host_impl_
->ScrollEnd();
1120 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1121 host_impl_
->ProcessScrollDeltas();
1122 EXPECT_TRUE(ScrollInfoContains(
1123 *scroll_info
.get(), scroll_layer
->id(),
1124 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
)));
1128 TEST_F(LayerTreeHostImplTest
, ScrollDuringPinchScrollsInnerViewport
) {
1129 LayerTreeSettings settings
= DefaultSettings();
1130 settings
.invert_viewport_scroll_order
= true;
1131 CreateHostImpl(settings
,
1132 CreateOutputSurface());
1134 const gfx::Size
content_size(1000, 1000);
1135 const gfx::Size
viewport_size(500, 500);
1136 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1138 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1139 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1142 gfx::Vector2dF(500, 500),
1143 outer_scroll_layer
->MaxScrollOffset());
1145 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1146 host_impl_
->PinchGestureBegin();
1147 host_impl_
->PinchGestureUpdate(2, gfx::Point(250, 250));
1148 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f
, 10.f
));
1149 host_impl_
->PinchGestureEnd();
1150 host_impl_
->ScrollEnd();
1153 gfx::Vector2dF(0, 0),
1154 outer_scroll_layer
->CurrentScrollOffset());
1156 gfx::Vector2dF(130, 130),
1157 inner_scroll_layer
->CurrentScrollOffset());
1160 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1161 // a pinch zoom is anchored within a certain margin of the screen edge, we
1162 // should assume the user means to scroll into the edge of the screen.
1163 TEST_F(LayerTreeHostImplTest
, PinchZoomSnapsToScreenEdge
) {
1164 LayerTreeSettings settings
= DefaultSettings();
1165 settings
.invert_viewport_scroll_order
= true;
1166 CreateHostImpl(settings
,
1167 CreateOutputSurface());
1169 const gfx::Size
content_size(1000, 1000);
1170 const gfx::Size
viewport_size(500, 500);
1171 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1173 int offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
- 5;
1174 gfx::Point
anchor(viewport_size
.width() - offsetFromEdge
,
1175 viewport_size
.height() - offsetFromEdge
);
1177 // Pinch in within the margins. The scroll should stay exactly locked to the
1178 // bottom and right.
1179 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1180 host_impl_
->PinchGestureBegin();
1181 host_impl_
->PinchGestureUpdate(2, anchor
);
1182 host_impl_
->PinchGestureEnd();
1183 host_impl_
->ScrollEnd();
1186 gfx::Vector2dF(250, 250),
1187 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1190 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1191 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1192 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1194 // Pinch in within the margins. The scroll should stay exactly locked to the
1196 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1197 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1198 host_impl_
->PinchGestureBegin();
1199 host_impl_
->PinchGestureUpdate(2, anchor
);
1200 host_impl_
->PinchGestureEnd();
1201 host_impl_
->ScrollEnd();
1204 gfx::Vector2dF(0, 0),
1205 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1208 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1209 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1210 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1212 // Pinch in just outside the margin. There should be no snapping.
1213 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1214 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1215 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1216 host_impl_
->PinchGestureBegin();
1217 host_impl_
->PinchGestureUpdate(2, anchor
);
1218 host_impl_
->PinchGestureEnd();
1219 host_impl_
->ScrollEnd();
1222 gfx::Vector2dF(50, 50),
1223 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1226 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1227 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1228 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1230 // Pinch in just outside the margin. There should be no snapping.
1231 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1232 anchor
= gfx::Point(viewport_size
.width() - offsetFromEdge
,
1233 viewport_size
.height() - offsetFromEdge
);
1234 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1235 host_impl_
->PinchGestureBegin();
1236 host_impl_
->PinchGestureUpdate(2, anchor
);
1237 host_impl_
->PinchGestureEnd();
1238 host_impl_
->ScrollEnd();
1241 gfx::Vector2dF(200, 200),
1242 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1245 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1246 const gfx::Size
content_size(200, 200);
1247 const gfx::Size
viewport_size(100, 100);
1248 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1250 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1251 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1253 // Zoom into the page by a 2X factor
1254 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1255 float page_scale_factor
= 2.f
;
1256 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1257 page_scale_factor
, min_page_scale
, max_page_scale
);
1258 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1260 // Scroll by a small amount, there should be no bubbling up to the inner
1262 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1263 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1264 host_impl_
->ScrollEnd();
1267 gfx::Vector2dF(5, 10),
1268 outer_scroll_layer
->CurrentScrollOffset());
1271 inner_scroll_layer
->CurrentScrollOffset());
1273 // Scroll by the outer viewport's max scroll extent, there the remainder
1274 // should bubble up to the inner viewport.
1275 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1276 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f
, 200.f
));
1277 host_impl_
->ScrollEnd();
1280 gfx::Vector2dF(100, 100),
1281 outer_scroll_layer
->CurrentScrollOffset());
1283 gfx::Vector2dF(5, 10),
1284 inner_scroll_layer
->CurrentScrollOffset());
1286 // Scroll by the inner viewport's max scroll extent, it should all go to the
1288 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1289 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f
, 80.f
));
1290 host_impl_
->ScrollEnd();
1293 gfx::Vector2dF(100, 100),
1294 outer_scroll_layer
->CurrentScrollOffset());
1296 gfx::Vector2dF(50, 50),
1297 inner_scroll_layer
->CurrentScrollOffset());
1300 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1301 ui::LatencyInfo latency_info
;
1302 latency_info
.trace_id
= 1234;
1303 scoped_ptr
<SwapPromise
> swap_promise(
1304 new LatencyInfoSwapPromise(latency_info
));
1306 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1307 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1308 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1309 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1310 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1311 host_impl_
->ScrollEnd();
1313 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1314 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1315 EXPECT_EQ(latency_info
.trace_id
, scroll_info
->swap_promises
[0]->TraceId());
1318 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1319 // up to the scroll_parent, rather than the stacking parent.
1320 TEST_F(LayerTreeHostImplTest
, ScrollBubblesToScrollParent
) {
1321 LayerImpl
* viewport_scroll
=
1322 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1323 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1325 // Set up two scrolling children of the root, one of which is a scroll parent
1326 // to the other. Scrolls bubbling from the child should bubble to the parent,
1327 // not the viewport.
1330 LayerImpl
*child_clip
;
1332 scoped_ptr
<LayerImpl
> scroll_parent_clip
=
1333 LayerImpl::Create(host_impl_
->active_tree(), 6);
1334 scoped_ptr
<LayerImpl
> scroll_parent
= CreateScrollableLayer(
1335 7, gfx::Size(10, 10), scroll_parent_clip
.get());
1336 parent
= scroll_parent
.get();
1337 scroll_parent_clip
->AddChild(scroll_parent
.Pass());
1339 viewport_scroll
->AddChild(scroll_parent_clip
.Pass());
1341 scoped_ptr
<LayerImpl
> scroll_child_clip
=
1342 LayerImpl::Create(host_impl_
->active_tree(), 8);
1343 scoped_ptr
<LayerImpl
> scroll_child
= CreateScrollableLayer(
1344 9, gfx::Size(10, 10), scroll_child_clip
.get());
1345 child
= scroll_child
.get();
1346 scroll_child
->SetPosition(gfx::Point(20, 20));
1347 scroll_child_clip
->AddChild(scroll_child
.Pass());
1349 child_clip
= scroll_child_clip
.get();
1350 viewport_scroll
->AddChild(scroll_child_clip
.Pass());
1352 child_clip
->SetScrollParent(parent
);
1357 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1358 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1359 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1360 host_impl_
->ScrollEnd();
1362 // The child should be fully scrolled by the first ScrollBy.
1363 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child
->CurrentScrollOffset());
1365 // The scroll_parent should receive the bubbled up second ScrollBy.
1366 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent
->CurrentScrollOffset());
1368 // The viewport shouldn't have been scrolled at all.
1370 gfx::Vector2dF(0, 0),
1371 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1373 gfx::Vector2dF(0, 0),
1374 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1378 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1379 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1380 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1381 host_impl_
->ScrollEnd();
1383 // The first ScrollBy should scroll the parent to its extent.
1384 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent
->CurrentScrollOffset());
1386 // The viewport should now be next in bubbling order.
1388 gfx::Vector2dF(2, 1),
1389 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1391 gfx::Vector2dF(0, 0),
1392 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1397 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1398 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1399 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1402 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1403 DCHECK(scroll_layer
);
1405 float min_page_scale
= 1.f
;
1406 float max_page_scale
= 4.f
;
1408 // Basic pinch zoom in gesture
1410 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1412 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1414 float page_scale_delta
= 2.f
;
1415 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1416 host_impl_
->PinchGestureBegin();
1417 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1418 host_impl_
->PinchGestureEnd();
1419 host_impl_
->ScrollEnd();
1420 EXPECT_FALSE(did_request_animate_
);
1421 EXPECT_TRUE(did_request_redraw_
);
1422 EXPECT_TRUE(did_request_commit_
);
1424 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1425 host_impl_
->ProcessScrollDeltas();
1426 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1431 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1433 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1434 float page_scale_delta
= 10.f
;
1436 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1437 host_impl_
->PinchGestureBegin();
1438 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1439 host_impl_
->PinchGestureEnd();
1440 host_impl_
->ScrollEnd();
1442 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1443 host_impl_
->ProcessScrollDeltas();
1444 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1447 // Zoom-out clamping
1449 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1451 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1452 scroll_layer
->PullDeltaForMainThread();
1453 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1455 float page_scale_delta
= 0.1f
;
1456 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1457 host_impl_
->PinchGestureBegin();
1458 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1459 host_impl_
->PinchGestureEnd();
1460 host_impl_
->ScrollEnd();
1462 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1463 host_impl_
->ProcessScrollDeltas();
1464 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1466 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1469 // Two-finger panning should not happen based on pinch events only
1471 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1473 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1474 scroll_layer
->PullDeltaForMainThread();
1475 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1477 float page_scale_delta
= 1.f
;
1478 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1479 host_impl_
->PinchGestureBegin();
1480 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1481 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1482 host_impl_
->PinchGestureEnd();
1483 host_impl_
->ScrollEnd();
1485 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1486 host_impl_
->ProcessScrollDeltas();
1487 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1488 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1491 // Two-finger panning should work with interleaved scroll events
1493 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1495 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1496 scroll_layer
->PullDeltaForMainThread();
1497 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1499 float page_scale_delta
= 1.f
;
1500 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1501 host_impl_
->PinchGestureBegin();
1502 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1503 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1504 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1505 host_impl_
->PinchGestureEnd();
1506 host_impl_
->ScrollEnd();
1508 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1509 host_impl_
->ProcessScrollDeltas();
1510 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1511 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1512 gfx::Vector2d(-10, -10)));
1515 // Two-finger panning should work when starting fully zoomed out.
1517 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1518 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1519 scroll_layer
->PullDeltaForMainThread();
1520 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1522 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1523 host_impl_
->PinchGestureBegin();
1524 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1525 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1526 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1527 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1528 host_impl_
->PinchGestureEnd();
1529 host_impl_
->ScrollEnd();
1531 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1532 host_impl_
->ProcessScrollDeltas();
1533 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1534 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1535 gfx::Vector2d(20, 20)));
1539 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1540 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1541 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1544 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1545 DCHECK(scroll_layer
);
1547 float min_page_scale
= 0.5f
;
1548 float max_page_scale
= 4.f
;
1549 base::TimeTicks start_time
= base::TimeTicks() +
1550 base::TimeDelta::FromSeconds(1);
1551 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1552 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1553 base::TimeTicks end_time
= start_time
+ duration
;
1555 // Non-anchor zoom-in
1557 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1559 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1561 did_request_redraw_
= false;
1562 did_request_animate_
= false;
1563 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1564 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1569 host_impl_
->ActivateSyncTree();
1570 EXPECT_FALSE(did_request_redraw_
);
1571 EXPECT_TRUE(did_request_animate_
);
1573 did_request_redraw_
= false;
1574 did_request_animate_
= false;
1575 host_impl_
->Animate(start_time
);
1576 EXPECT_TRUE(did_request_redraw_
);
1577 EXPECT_TRUE(did_request_animate_
);
1579 did_request_redraw_
= false;
1580 did_request_animate_
= false;
1581 host_impl_
->Animate(halfway_through_animation
);
1582 EXPECT_TRUE(did_request_redraw_
);
1583 EXPECT_TRUE(did_request_animate_
);
1585 did_request_redraw_
= false;
1586 did_request_animate_
= false;
1587 did_request_commit_
= false;
1588 host_impl_
->Animate(end_time
);
1589 EXPECT_TRUE(did_request_commit_
);
1590 EXPECT_FALSE(did_request_animate_
);
1592 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1593 host_impl_
->ProcessScrollDeltas();
1594 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1595 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1596 gfx::Vector2d(-50, -50)));
1601 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1603 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1605 did_request_redraw_
= false;
1606 did_request_animate_
= false;
1607 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1608 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1609 gfx::Vector2d(25, 25),
1613 host_impl_
->ActivateSyncTree();
1614 EXPECT_FALSE(did_request_redraw_
);
1615 EXPECT_TRUE(did_request_animate_
);
1617 did_request_redraw_
= false;
1618 did_request_animate_
= false;
1619 host_impl_
->Animate(start_time
);
1620 EXPECT_TRUE(did_request_redraw_
);
1621 EXPECT_TRUE(did_request_animate_
);
1623 did_request_redraw_
= false;
1624 did_request_commit_
= false;
1625 did_request_animate_
= false;
1626 host_impl_
->Animate(end_time
);
1627 EXPECT_TRUE(did_request_redraw_
);
1628 EXPECT_FALSE(did_request_animate_
);
1629 EXPECT_TRUE(did_request_commit_
);
1631 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1632 host_impl_
->ProcessScrollDeltas();
1633 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1634 // Pushed to (0,0) via clamping against contents layer size.
1635 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1636 gfx::Vector2d(-50, -50)));
1640 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1641 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1642 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1645 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1646 DCHECK(scroll_layer
);
1648 float min_page_scale
= 0.5f
;
1649 float max_page_scale
= 4.f
;
1650 base::TimeTicks start_time
= base::TimeTicks() +
1651 base::TimeDelta::FromSeconds(1);
1652 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1653 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1654 base::TimeTicks end_time
= start_time
+ duration
;
1656 // Anchor zoom with unchanged page scale should not change scroll or scale.
1658 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1660 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1662 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1663 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1668 host_impl_
->ActivateSyncTree();
1669 host_impl_
->Animate(start_time
);
1670 host_impl_
->Animate(halfway_through_animation
);
1671 EXPECT_TRUE(did_request_redraw_
);
1672 host_impl_
->Animate(end_time
);
1673 EXPECT_TRUE(did_request_commit_
);
1675 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1676 host_impl_
->ProcessScrollDeltas();
1677 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1678 ExpectNone(*scroll_info
, scroll_layer
->id());
1682 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1683 host_impl_
->CreatePendingTree();
1684 CreateScrollAndContentsLayers(
1685 host_impl_
->pending_tree(),
1686 gfx::Size(100, 100));
1687 host_impl_
->ActivateSyncTree();
1690 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1691 DCHECK(scroll_layer
);
1693 float min_page_scale
= 0.5f
;
1694 float max_page_scale
= 4.f
;
1695 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1697 host_impl_
->ActivateSyncTree();
1699 base::TimeTicks start_time
= base::TimeTicks() +
1700 base::TimeDelta::FromSeconds(1);
1701 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1702 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1703 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1704 base::TimeTicks end_time
= start_time
+ duration
;
1705 float target_scale
= 2.f
;
1707 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1709 // Make sure TakePageScaleAnimation works properly.
1711 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1712 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1717 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1718 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1719 EXPECT_EQ(target_scale
, psa
->scale
);
1720 EXPECT_EQ(duration
, psa
->duration
);
1721 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1723 // Recreate the PSA. Nothing should happen here since the tree containing the
1724 // PSA hasn't been activated yet.
1725 did_request_redraw_
= false;
1726 did_request_animate_
= false;
1727 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1728 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1733 host_impl_
->Animate(halfway_through_animation
);
1734 EXPECT_FALSE(did_request_animate_
);
1735 EXPECT_FALSE(did_request_redraw_
);
1737 // Activate the sync tree. This should cause the animation to become enabled.
1738 // It should also clear the pointer on the sync tree.
1739 host_impl_
->ActivateSyncTree();
1741 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1742 EXPECT_FALSE(did_request_redraw_
);
1743 EXPECT_TRUE(did_request_animate_
);
1745 // From here on, make sure the animation runs as normal.
1746 did_request_redraw_
= false;
1747 did_request_animate_
= false;
1748 host_impl_
->Animate(start_time
);
1749 EXPECT_TRUE(did_request_redraw_
);
1750 EXPECT_TRUE(did_request_animate_
);
1752 did_request_redraw_
= false;
1753 did_request_animate_
= false;
1754 host_impl_
->Animate(third_through_animation
);
1755 EXPECT_TRUE(did_request_redraw_
);
1756 EXPECT_TRUE(did_request_animate_
);
1758 // Another activation shouldn't have any effect on the animation.
1759 host_impl_
->ActivateSyncTree();
1761 did_request_redraw_
= false;
1762 did_request_animate_
= false;
1763 host_impl_
->Animate(halfway_through_animation
);
1764 EXPECT_TRUE(did_request_redraw_
);
1765 EXPECT_TRUE(did_request_animate_
);
1767 did_request_redraw_
= false;
1768 did_request_animate_
= false;
1769 did_request_commit_
= false;
1770 host_impl_
->Animate(end_time
);
1771 EXPECT_TRUE(did_request_commit_
);
1772 EXPECT_FALSE(did_request_animate_
);
1774 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1775 host_impl_
->ProcessScrollDeltas();
1776 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
1777 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1778 gfx::Vector2d(-50, -50)));
1781 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
1782 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1783 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1786 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1787 DCHECK(scroll_layer
);
1789 base::TimeTicks start_time
=
1790 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1791 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1792 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1793 base::TimeTicks end_time
= start_time
+ duration
;
1795 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1796 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1798 did_complete_page_scale_animation_
= false;
1799 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1800 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1801 gfx::Vector2d(), false, 2.f
, duration
)));
1802 host_impl_
->ActivateSyncTree();
1803 host_impl_
->Animate(start_time
);
1804 EXPECT_FALSE(did_complete_page_scale_animation_
);
1806 host_impl_
->Animate(halfway_through_animation
);
1807 EXPECT_FALSE(did_complete_page_scale_animation_
);
1809 host_impl_
->Animate(end_time
);
1810 EXPECT_TRUE(did_complete_page_scale_animation_
);
1813 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
1815 LayerTreeHostImplOverridePhysicalTime(
1816 const LayerTreeSettings
& settings
,
1817 LayerTreeHostImplClient
* client
,
1819 SharedBitmapManager
* manager
,
1820 TaskGraphRunner
* task_graph_runner
,
1821 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
1822 : LayerTreeHostImpl(settings
,
1825 rendering_stats_instrumentation
,
1831 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
1832 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
1833 fake_current_physical_time_
);
1836 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
1837 fake_current_physical_time_
= fake_now
;
1841 base::TimeTicks fake_current_physical_time_
;
1844 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
1846 void SetupLayers(LayerTreeSettings settings
) {
1847 gfx::Size
viewport_size(10, 10);
1848 gfx::Size
content_size(100, 100);
1850 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
1851 new LayerTreeHostImplOverridePhysicalTime(
1852 settings
, this, &proxy_
, &shared_bitmap_manager_
,
1853 &task_graph_runner_
, &stats_instrumentation_
);
1854 host_impl_
= make_scoped_ptr(host_impl_override_time
);
1855 host_impl_
->InitializeRenderer(CreateOutputSurface());
1856 host_impl_
->SetViewportSize(viewport_size
);
1858 scoped_ptr
<LayerImpl
> root
=
1859 LayerImpl::Create(host_impl_
->active_tree(), 1);
1860 root
->SetBounds(viewport_size
);
1862 scoped_ptr
<LayerImpl
> scroll
=
1863 LayerImpl::Create(host_impl_
->active_tree(), 2);
1864 scroll
->SetScrollClipLayer(root
->id());
1865 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1866 root
->SetBounds(viewport_size
);
1867 scroll
->SetBounds(content_size
);
1868 scroll
->SetIsContainerForFixedPositionLayers(true);
1870 scoped_ptr
<LayerImpl
> contents
=
1871 LayerImpl::Create(host_impl_
->active_tree(), 3);
1872 contents
->SetDrawsContent(true);
1873 contents
->SetBounds(content_size
);
1875 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
1876 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 4,
1877 VERTICAL
, 10, 0, false, true);
1878 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
1880 scroll
->AddChild(contents
.Pass());
1881 root
->AddChild(scroll
.Pass());
1882 root
->SetHasRenderSurface(true);
1883 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1884 root
->AddChild(scrollbar
.Pass());
1886 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1887 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
1889 host_impl_
->active_tree()->DidBecomeActive();
1893 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
1894 LayerTreeSettings settings
;
1895 settings
.scrollbar_animator
= animator
;
1896 settings
.scrollbar_fade_delay_ms
= 20;
1897 settings
.scrollbar_fade_duration_ms
= 20;
1899 SetupLayers(settings
);
1901 base::TimeTicks fake_now
= base::TimeTicks::Now();
1903 EXPECT_FALSE(did_request_animate_
);
1904 EXPECT_FALSE(did_request_redraw_
);
1905 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1906 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1908 // If no scroll happened during a scroll gesture, it should have no effect.
1909 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1910 host_impl_
->ScrollEnd();
1911 EXPECT_FALSE(did_request_animate_
);
1912 EXPECT_FALSE(did_request_redraw_
);
1913 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1914 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1916 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1918 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1919 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1920 EXPECT_FALSE(did_request_animate_
);
1921 EXPECT_TRUE(did_request_redraw_
);
1922 did_request_redraw_
= false;
1923 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1924 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1926 host_impl_
->ScrollEnd();
1927 EXPECT_FALSE(did_request_animate_
);
1928 EXPECT_FALSE(did_request_redraw_
);
1929 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1930 requested_animation_delay_
);
1931 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1933 fake_now
+= requested_animation_delay_
;
1934 requested_animation_delay_
= base::TimeDelta();
1935 animation_task_
.Run();
1936 animation_task_
= base::Closure();
1937 EXPECT_TRUE(did_request_animate_
);
1938 did_request_animate_
= false;
1939 EXPECT_FALSE(did_request_redraw_
);
1941 // After the scrollbar animation begins, we should start getting redraws.
1942 host_impl_
->Animate(fake_now
);
1943 EXPECT_TRUE(did_request_animate_
);
1944 did_request_animate_
= false;
1945 EXPECT_TRUE(did_request_redraw_
);
1946 did_request_redraw_
= false;
1947 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1948 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1950 // Setting the scroll offset outside a scroll should also cause the
1951 // scrollbar to appear and to schedule a scrollbar animation.
1952 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1953 gfx::ScrollOffset(5, 5));
1954 EXPECT_FALSE(did_request_animate_
);
1955 EXPECT_FALSE(did_request_redraw_
);
1956 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1957 requested_animation_delay_
);
1958 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1959 requested_animation_delay_
= base::TimeDelta();
1960 animation_task_
= base::Closure();
1962 // Scrollbar animation is not triggered unnecessarily.
1963 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1964 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1965 EXPECT_FALSE(did_request_animate_
);
1966 EXPECT_TRUE(did_request_redraw_
);
1967 did_request_redraw_
= false;
1968 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1969 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1971 host_impl_
->ScrollEnd();
1972 EXPECT_FALSE(did_request_animate_
);
1973 EXPECT_FALSE(did_request_redraw_
);
1974 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1975 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1977 // Changing page scale triggers scrollbar animation.
1978 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
1979 host_impl_
->SetPageScaleOnActiveTree(1.1f
);
1980 EXPECT_FALSE(did_request_animate_
);
1981 EXPECT_FALSE(did_request_redraw_
);
1982 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1983 requested_animation_delay_
);
1984 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1985 requested_animation_delay_
= base::TimeDelta();
1986 animation_task_
= base::Closure();
1990 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
1991 RunTest(LayerTreeSettings::LINEAR_FADE
);
1994 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
1995 RunTest(LayerTreeSettings::THINNING
);
1998 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1999 float device_scale_factor
) {
2000 LayerTreeSettings settings
;
2001 settings
.scrollbar_fade_delay_ms
= 500;
2002 settings
.scrollbar_fade_duration_ms
= 300;
2003 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
2005 gfx::Size
viewport_size(300, 200);
2006 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
2007 gfx::ScaleSize(viewport_size
, device_scale_factor
));
2008 gfx::Size
content_size(1000, 1000);
2010 CreateHostImpl(settings
, CreateOutputSurface());
2011 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
2012 host_impl_
->SetViewportSize(device_viewport_size
);
2014 scoped_ptr
<LayerImpl
> root
=
2015 LayerImpl::Create(host_impl_
->active_tree(), 1);
2016 root
->SetBounds(viewport_size
);
2017 root
->SetHasRenderSurface(true);
2019 scoped_ptr
<LayerImpl
> scroll
=
2020 LayerImpl::Create(host_impl_
->active_tree(), 2);
2021 scroll
->SetScrollClipLayer(root
->id());
2022 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2023 scroll
->SetBounds(content_size
);
2024 scroll
->SetIsContainerForFixedPositionLayers(true);
2026 scoped_ptr
<LayerImpl
> contents
=
2027 LayerImpl::Create(host_impl_
->active_tree(), 3);
2028 contents
->SetDrawsContent(true);
2029 contents
->SetBounds(content_size
);
2031 // The scrollbar is on the right side.
2032 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
2033 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
2034 scrollbar
->SetDrawsContent(true);
2035 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
2036 scrollbar
->SetPosition(gfx::Point(285, 0));
2038 scroll
->AddChild(contents
.Pass());
2039 root
->AddChild(scroll
.Pass());
2040 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
2041 root
->AddChild(scrollbar
.Pass());
2043 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2044 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
2046 host_impl_
->active_tree()->DidBecomeActive();
2049 LayerImpl
* root_scroll
=
2050 host_impl_
->active_tree()->InnerViewportScrollLayer();
2051 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
2052 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
2053 static_cast<ScrollbarAnimationControllerThinning
*>(
2054 root_scroll
->scrollbar_animation_controller());
2055 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
2057 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
2058 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2060 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
2061 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2063 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2064 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2066 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
2067 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2068 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2070 did_request_redraw_
= false;
2071 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2072 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
2073 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2074 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
2075 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2076 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
2077 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2080 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
2081 SetupMouseMoveAtWithDeviceScale(1.f
);
2084 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
2085 SetupMouseMoveAtWithDeviceScale(2.f
);
2088 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
2089 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2090 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2091 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2094 CompositorFrameMetadata metadata
=
2095 host_impl_
->MakeCompositorFrameMetadata();
2096 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
2097 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
2098 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
2099 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2100 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2101 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2102 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2103 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2106 // Scrolling should update metadata immediately.
2107 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2108 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2109 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2111 CompositorFrameMetadata metadata
=
2112 host_impl_
->MakeCompositorFrameMetadata();
2113 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2115 host_impl_
->ScrollEnd();
2117 CompositorFrameMetadata metadata
=
2118 host_impl_
->MakeCompositorFrameMetadata();
2119 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2122 // Root "overflow: hidden" properties should be reflected on the outer
2123 // viewport scroll layer.
2125 host_impl_
->active_tree()
2126 ->OuterViewportScrollLayer()
2127 ->set_user_scrollable_horizontal(false);
2128 CompositorFrameMetadata metadata
=
2129 host_impl_
->MakeCompositorFrameMetadata();
2130 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2131 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2133 host_impl_
->active_tree()
2134 ->OuterViewportScrollLayer()
2135 ->set_user_scrollable_vertical(false);
2136 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2137 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2138 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2141 // Page scale should update metadata correctly (shrinking only the viewport).
2142 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
2143 host_impl_
->PinchGestureBegin();
2144 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
2145 host_impl_
->PinchGestureEnd();
2146 host_impl_
->ScrollEnd();
2148 CompositorFrameMetadata metadata
=
2149 host_impl_
->MakeCompositorFrameMetadata();
2150 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2151 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
2152 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
2153 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2154 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2155 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2158 // Likewise if set from the main thread.
2159 host_impl_
->ProcessScrollDeltas();
2160 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
2161 host_impl_
->SetPageScaleOnActiveTree(4.f
);
2163 CompositorFrameMetadata metadata
=
2164 host_impl_
->MakeCompositorFrameMetadata();
2165 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2166 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
2167 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
2168 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2169 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2170 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2174 class DidDrawCheckLayer
: public LayerImpl
{
2176 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2177 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2180 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2181 will_draw_called_
= true;
2182 if (will_draw_returns_false_
)
2184 return LayerImpl::WillDraw(draw_mode
, provider
);
2187 void AppendQuads(RenderPass
* render_pass
,
2188 AppendQuadsData
* append_quads_data
) override
{
2189 append_quads_called_
= true;
2190 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2193 void DidDraw(ResourceProvider
* provider
) override
{
2194 did_draw_called_
= true;
2195 LayerImpl::DidDraw(provider
);
2198 bool will_draw_called() const { return will_draw_called_
; }
2199 bool append_quads_called() const { return append_quads_called_
; }
2200 bool did_draw_called() const { return did_draw_called_
; }
2202 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2204 void ClearDidDrawCheck() {
2205 will_draw_called_
= false;
2206 append_quads_called_
= false;
2207 did_draw_called_
= false;
2210 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2212 void AddCopyRequest() {
2213 ScopedPtrVector
<CopyOutputRequest
> requests
;
2215 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2216 SetHasRenderSurface(true);
2217 PassCopyRequests(&requests
);
2221 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2222 : LayerImpl(tree_impl
, id
),
2223 will_draw_returns_false_(false),
2224 will_draw_called_(false),
2225 append_quads_called_(false),
2226 did_draw_called_(false) {
2227 SetBounds(gfx::Size(10, 10));
2228 SetDrawsContent(true);
2229 draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
2233 bool will_draw_returns_false_
;
2234 bool will_draw_called_
;
2235 bool append_quads_called_
;
2236 bool did_draw_called_
;
2239 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2240 // The root layer is always drawn, so run this test on a child layer that
2241 // will be masked out by the root layer's bounds.
2242 host_impl_
->active_tree()->SetRootLayer(
2243 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2244 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2245 host_impl_
->active_tree()->root_layer());
2247 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2248 root
->SetHasRenderSurface(true);
2249 DidDrawCheckLayer
* layer
=
2250 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2253 LayerTreeHostImpl::FrameData frame
;
2254 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2255 host_impl_
->DrawLayers(&frame
);
2256 host_impl_
->DidDrawAllLayers(frame
);
2258 EXPECT_TRUE(layer
->will_draw_called());
2259 EXPECT_TRUE(layer
->append_quads_called());
2260 EXPECT_TRUE(layer
->did_draw_called());
2263 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2266 LayerTreeHostImpl::FrameData frame
;
2268 layer
->set_will_draw_returns_false();
2269 layer
->ClearDidDrawCheck();
2271 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2272 host_impl_
->DrawLayers(&frame
);
2273 host_impl_
->DidDrawAllLayers(frame
);
2275 EXPECT_TRUE(layer
->will_draw_called());
2276 EXPECT_FALSE(layer
->append_quads_called());
2277 EXPECT_FALSE(layer
->did_draw_called());
2281 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2282 // The root layer is always drawn, so run this test on a child layer that
2283 // will be masked out by the root layer's bounds.
2284 host_impl_
->active_tree()->SetRootLayer(
2285 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2286 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2287 host_impl_
->active_tree()->root_layer());
2288 root
->SetMasksToBounds(true);
2289 root
->SetHasRenderSurface(true);
2290 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2291 DidDrawCheckLayer
* layer
=
2292 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2293 // Ensure visible_layer_rect for layer is empty.
2294 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2295 layer
->SetBounds(gfx::Size(10, 10));
2297 LayerTreeHostImpl::FrameData frame
;
2299 EXPECT_FALSE(layer
->will_draw_called());
2300 EXPECT_FALSE(layer
->did_draw_called());
2302 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2303 host_impl_
->DrawLayers(&frame
);
2304 host_impl_
->DidDrawAllLayers(frame
);
2306 EXPECT_FALSE(layer
->will_draw_called());
2307 EXPECT_FALSE(layer
->did_draw_called());
2309 EXPECT_TRUE(layer
->visible_layer_rect().IsEmpty());
2311 // Ensure visible_layer_rect for layer is not empty
2312 layer
->SetPosition(gfx::PointF());
2314 EXPECT_FALSE(layer
->will_draw_called());
2315 EXPECT_FALSE(layer
->did_draw_called());
2317 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2318 host_impl_
->DrawLayers(&frame
);
2319 host_impl_
->DidDrawAllLayers(frame
);
2321 EXPECT_TRUE(layer
->will_draw_called());
2322 EXPECT_TRUE(layer
->did_draw_called());
2324 EXPECT_FALSE(layer
->visible_layer_rect().IsEmpty());
2327 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2328 gfx::Size
big_size(1000, 1000);
2329 host_impl_
->SetViewportSize(big_size
);
2331 host_impl_
->active_tree()->SetRootLayer(
2332 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2333 DidDrawCheckLayer
* root
=
2334 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2336 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2337 DidDrawCheckLayer
* occluded_layer
=
2338 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2340 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2341 root
->SetHasRenderSurface(true);
2342 DidDrawCheckLayer
* top_layer
=
2343 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2344 // This layer covers the occluded_layer above. Make this layer large so it can
2346 top_layer
->SetBounds(big_size
);
2347 top_layer
->SetContentsOpaque(true);
2349 LayerTreeHostImpl::FrameData frame
;
2351 EXPECT_FALSE(occluded_layer
->will_draw_called());
2352 EXPECT_FALSE(occluded_layer
->did_draw_called());
2353 EXPECT_FALSE(top_layer
->will_draw_called());
2354 EXPECT_FALSE(top_layer
->did_draw_called());
2356 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2357 host_impl_
->DrawLayers(&frame
);
2358 host_impl_
->DidDrawAllLayers(frame
);
2360 EXPECT_FALSE(occluded_layer
->will_draw_called());
2361 EXPECT_FALSE(occluded_layer
->did_draw_called());
2362 EXPECT_TRUE(top_layer
->will_draw_called());
2363 EXPECT_TRUE(top_layer
->did_draw_called());
2366 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2367 host_impl_
->active_tree()->SetRootLayer(
2368 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2369 DidDrawCheckLayer
* root
=
2370 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2372 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2373 root
->SetHasRenderSurface(true);
2374 DidDrawCheckLayer
* layer1
=
2375 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2377 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2378 DidDrawCheckLayer
* layer2
=
2379 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2381 layer1
->SetHasRenderSurface(true);
2382 layer1
->SetShouldFlattenTransform(true);
2384 EXPECT_FALSE(root
->did_draw_called());
2385 EXPECT_FALSE(layer1
->did_draw_called());
2386 EXPECT_FALSE(layer2
->did_draw_called());
2388 LayerTreeHostImpl::FrameData frame
;
2389 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2390 host_impl_
->active_tree()->root_layer());
2391 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2392 host_impl_
->DrawLayers(&frame
);
2393 host_impl_
->DidDrawAllLayers(frame
);
2395 EXPECT_TRUE(root
->did_draw_called());
2396 EXPECT_TRUE(layer1
->did_draw_called());
2397 EXPECT_TRUE(layer2
->did_draw_called());
2399 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2400 EXPECT_TRUE(layer1
->render_surface());
2403 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2405 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2408 bool had_incomplete_tile
,
2410 ResourceProvider
* resource_provider
) {
2411 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2414 had_incomplete_tile
,
2416 resource_provider
));
2419 void AppendQuads(RenderPass
* render_pass
,
2420 AppendQuadsData
* append_quads_data
) override
{
2421 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2422 if (had_incomplete_tile_
)
2423 append_quads_data
->num_incomplete_tiles
++;
2425 append_quads_data
->num_missing_tiles
++;
2429 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2432 bool had_incomplete_tile
,
2434 ResourceProvider
* resource_provider
)
2435 : DidDrawCheckLayer(tree_impl
, id
),
2436 tile_missing_(tile_missing
),
2437 had_incomplete_tile_(had_incomplete_tile
) {
2439 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2443 bool had_incomplete_tile_
;
2446 struct PrepareToDrawSuccessTestCase
{
2448 bool has_missing_tile
= false;
2449 bool has_incomplete_tile
= false;
2450 bool is_animating
= false;
2451 bool has_copy_request
= false;
2453 bool high_res_required
= false;
2455 State layer_between
;
2457 DrawResult expected_result
;
2459 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2460 : expected_result(result
) {}
2463 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2464 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2467 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2468 // 1. Animated layer first.
2469 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2470 cases
.back().layer_before
.is_animating
= true;
2471 // 2. Animated layer between.
2472 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2473 cases
.back().layer_between
.is_animating
= true;
2474 // 3. Animated layer last.
2475 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2476 cases
.back().layer_after
.is_animating
= true;
2477 // 4. Missing tile first.
2478 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2479 cases
.back().layer_before
.has_missing_tile
= true;
2480 // 5. Missing tile between.
2481 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2482 cases
.back().layer_between
.has_missing_tile
= true;
2483 // 6. Missing tile last.
2484 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2485 cases
.back().layer_after
.has_missing_tile
= true;
2486 // 7. Incomplete tile first.
2487 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2488 cases
.back().layer_before
.has_incomplete_tile
= true;
2489 // 8. Incomplete tile between.
2490 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2491 cases
.back().layer_between
.has_incomplete_tile
= true;
2492 // 9. Incomplete tile last.
2493 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2494 cases
.back().layer_after
.has_incomplete_tile
= true;
2495 // 10. Animation with missing tile.
2497 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2498 cases
.back().layer_between
.has_missing_tile
= true;
2499 cases
.back().layer_between
.is_animating
= true;
2500 // 11. Animation with incomplete tile.
2501 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2502 cases
.back().layer_between
.has_incomplete_tile
= true;
2503 cases
.back().layer_between
.is_animating
= true;
2505 // 12. High res required.
2506 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2507 cases
.back().high_res_required
= true;
2508 // 13. High res required with incomplete tile.
2510 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2511 cases
.back().high_res_required
= true;
2512 cases
.back().layer_between
.has_incomplete_tile
= true;
2513 // 14. High res required with missing tile.
2515 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2516 cases
.back().high_res_required
= true;
2517 cases
.back().layer_between
.has_missing_tile
= true;
2519 // 15. High res required is higher priority than animating missing tiles.
2521 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2522 cases
.back().high_res_required
= true;
2523 cases
.back().layer_between
.has_missing_tile
= true;
2524 cases
.back().layer_after
.has_missing_tile
= true;
2525 cases
.back().layer_after
.is_animating
= true;
2526 // 16. High res required is higher priority than animating missing tiles.
2528 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2529 cases
.back().high_res_required
= true;
2530 cases
.back().layer_between
.has_missing_tile
= true;
2531 cases
.back().layer_before
.has_missing_tile
= true;
2532 cases
.back().layer_before
.is_animating
= true;
2534 host_impl_
->active_tree()->SetRootLayer(
2535 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2536 DidDrawCheckLayer
* root
=
2537 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2538 root
->SetHasRenderSurface(true);
2540 LayerTreeHostImpl::FrameData frame
;
2541 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2542 host_impl_
->DrawLayers(&frame
);
2543 host_impl_
->DidDrawAllLayers(frame
);
2544 host_impl_
->SwapBuffers(frame
);
2546 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2547 const auto& testcase
= cases
[i
];
2548 std::vector
<LayerImpl
*> to_remove
;
2549 for (auto* child
: root
->children())
2550 to_remove
.push_back(child
);
2551 for (auto* child
: to_remove
)
2552 root
->RemoveChild(child
);
2554 std::ostringstream scope
;
2555 scope
<< "Test case: " << i
;
2556 SCOPED_TRACE(scope
.str());
2558 root
->AddChild(MissingTextureAnimatingLayer::Create(
2559 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2560 testcase
.layer_before
.has_incomplete_tile
,
2561 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2562 DidDrawCheckLayer
* before
=
2563 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2564 if (testcase
.layer_before
.has_copy_request
)
2565 before
->AddCopyRequest();
2567 root
->AddChild(MissingTextureAnimatingLayer::Create(
2568 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2569 testcase
.layer_between
.has_incomplete_tile
,
2570 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2571 DidDrawCheckLayer
* between
=
2572 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2573 if (testcase
.layer_between
.has_copy_request
)
2574 between
->AddCopyRequest();
2576 root
->AddChild(MissingTextureAnimatingLayer::Create(
2577 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2578 testcase
.layer_after
.has_incomplete_tile
,
2579 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2580 DidDrawCheckLayer
* after
=
2581 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2582 if (testcase
.layer_after
.has_copy_request
)
2583 after
->AddCopyRequest();
2585 if (testcase
.high_res_required
)
2586 host_impl_
->SetRequiresHighResToDraw();
2588 LayerTreeHostImpl::FrameData frame
;
2589 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2590 host_impl_
->DrawLayers(&frame
);
2591 host_impl_
->DidDrawAllLayers(frame
);
2592 host_impl_
->SwapBuffers(frame
);
2596 TEST_F(LayerTreeHostImplTest
,
2597 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2598 CreateHostImpl(DefaultSettings(),
2599 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2600 EXPECT_TRUE(host_impl_
->output_surface()
2602 .draw_and_swap_full_viewport_every_frame
);
2604 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2607 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2608 // 1. Animation with missing tile.
2609 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2610 cases
.back().layer_between
.has_missing_tile
= true;
2611 cases
.back().layer_between
.is_animating
= true;
2612 // 2. High res required with incomplete tile.
2613 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2614 cases
.back().high_res_required
= true;
2615 cases
.back().layer_between
.has_incomplete_tile
= true;
2616 // 3. High res required with missing tile.
2617 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2618 cases
.back().high_res_required
= true;
2619 cases
.back().layer_between
.has_missing_tile
= true;
2621 host_impl_
->active_tree()->SetRootLayer(
2622 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2623 DidDrawCheckLayer
* root
=
2624 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2625 root
->SetHasRenderSurface(true);
2627 LayerTreeHostImpl::FrameData frame
;
2628 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2629 host_impl_
->DrawLayers(&frame
);
2630 host_impl_
->DidDrawAllLayers(frame
);
2631 host_impl_
->SwapBuffers(frame
);
2633 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2634 const auto& testcase
= cases
[i
];
2635 std::vector
<LayerImpl
*> to_remove
;
2636 for (auto* child
: root
->children())
2637 to_remove
.push_back(child
);
2638 for (auto* child
: to_remove
)
2639 root
->RemoveChild(child
);
2641 std::ostringstream scope
;
2642 scope
<< "Test case: " << i
;
2643 SCOPED_TRACE(scope
.str());
2645 root
->AddChild(MissingTextureAnimatingLayer::Create(
2646 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2647 testcase
.layer_before
.has_incomplete_tile
,
2648 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2649 DidDrawCheckLayer
* before
=
2650 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2651 if (testcase
.layer_before
.has_copy_request
)
2652 before
->AddCopyRequest();
2654 root
->AddChild(MissingTextureAnimatingLayer::Create(
2655 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2656 testcase
.layer_between
.has_incomplete_tile
,
2657 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2658 DidDrawCheckLayer
* between
=
2659 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2660 if (testcase
.layer_between
.has_copy_request
)
2661 between
->AddCopyRequest();
2663 root
->AddChild(MissingTextureAnimatingLayer::Create(
2664 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2665 testcase
.layer_after
.has_incomplete_tile
,
2666 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2667 DidDrawCheckLayer
* after
=
2668 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2669 if (testcase
.layer_after
.has_copy_request
)
2670 after
->AddCopyRequest();
2672 if (testcase
.high_res_required
)
2673 host_impl_
->SetRequiresHighResToDraw();
2675 LayerTreeHostImpl::FrameData frame
;
2676 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2677 host_impl_
->DrawLayers(&frame
);
2678 host_impl_
->DidDrawAllLayers(frame
);
2679 host_impl_
->SwapBuffers(frame
);
2683 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2684 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2685 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2686 root
->SetHasRenderSurface(true);
2687 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2690 // Scroll event is ignored because layer is not scrollable.
2691 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2692 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2693 EXPECT_FALSE(did_request_redraw_
);
2694 EXPECT_FALSE(did_request_commit_
);
2697 // TODO(bokan): Convert these tests to create inner and outer viewports.
2698 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
2700 LayerTreeHostImplTopControlsTest()
2701 // Make the clip size the same as the layer (content) size so the layer is
2703 : layer_size_(10, 10),
2704 clip_size_(layer_size_
),
2705 top_controls_height_(50) {
2706 viewport_size_
= gfx::Size(clip_size_
.width(),
2707 clip_size_
.height() + top_controls_height_
);
2710 bool CreateHostImpl(const LayerTreeSettings
& settings
,
2711 scoped_ptr
<OutputSurface
> output_surface
) override
{
2713 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
2715 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
2716 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2721 void SetupTopControlsAndScrollLayer() {
2722 scoped_ptr
<LayerImpl
> root
=
2723 LayerImpl::Create(host_impl_
->active_tree(), 1);
2724 scoped_ptr
<LayerImpl
> root_clip
=
2725 LayerImpl::Create(host_impl_
->active_tree(), 2);
2726 root_clip
->SetBounds(clip_size_
);
2727 root
->SetScrollClipLayer(root_clip
->id());
2728 root
->SetBounds(layer_size_
);
2729 root
->SetPosition(gfx::PointF());
2730 root
->SetDrawsContent(false);
2731 root
->SetIsContainerForFixedPositionLayers(true);
2732 int inner_viewport_scroll_layer_id
= root
->id();
2733 int page_scale_layer_id
= root_clip
->id();
2734 root_clip
->SetHasRenderSurface(true);
2735 root_clip
->AddChild(root
.Pass());
2736 root_clip
->SetHasRenderSurface(true);
2737 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2738 host_impl_
->active_tree()->SetViewportLayersFromIds(
2739 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2741 // Set a viewport size that is large enough to contain both the top controls
2742 // and some content.
2743 host_impl_
->SetViewportSize(viewport_size_
);
2744 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2746 host_impl_
->DidChangeTopControlsPosition();
2748 host_impl_
->CreatePendingTree();
2749 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2751 LayerImpl::Create(host_impl_
->sync_tree(), 1);
2753 LayerImpl::Create(host_impl_
->sync_tree(), 2);
2754 root_clip
->SetBounds(clip_size_
);
2755 root
->SetScrollClipLayer(root_clip
->id());
2756 root
->SetBounds(layer_size_
);
2757 root
->SetPosition(gfx::PointF());
2758 root
->SetDrawsContent(false);
2759 root
->SetIsContainerForFixedPositionLayers(true);
2760 inner_viewport_scroll_layer_id
= root
->id();
2761 page_scale_layer_id
= root_clip
->id();
2762 root_clip
->AddChild(root
.Pass());
2763 host_impl_
->sync_tree()->SetRootLayer(root_clip
.Pass());
2764 host_impl_
->sync_tree()->SetViewportLayersFromIds(
2765 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2767 // Set a viewport size that is large enough to contain both the top controls
2768 // and some content.
2769 host_impl_
->SetViewportSize(viewport_size_
);
2770 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2771 host_impl_
->DidChangeTopControlsPosition();
2774 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2775 const gfx::Size
& inner_viewport_size
,
2776 const gfx::Size
& outer_viewport_size
,
2777 const gfx::Size
& scroll_layer_size
) {
2778 CreateHostImpl(settings_
, CreateOutputSurface());
2779 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2780 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2781 host_impl_
->DidChangeTopControlsPosition();
2783 scoped_ptr
<LayerImpl
> root
=
2784 LayerImpl::Create(host_impl_
->active_tree(), 1);
2785 scoped_ptr
<LayerImpl
> root_clip
=
2786 LayerImpl::Create(host_impl_
->active_tree(), 2);
2787 scoped_ptr
<LayerImpl
> page_scale
=
2788 LayerImpl::Create(host_impl_
->active_tree(), 3);
2790 scoped_ptr
<LayerImpl
> outer_scroll
=
2791 LayerImpl::Create(host_impl_
->active_tree(), 4);
2792 scoped_ptr
<LayerImpl
> outer_clip
=
2793 LayerImpl::Create(host_impl_
->active_tree(), 5);
2795 root_clip
->SetBounds(inner_viewport_size
);
2796 root
->SetScrollClipLayer(root_clip
->id());
2797 root
->SetBounds(outer_viewport_size
);
2798 root
->SetPosition(gfx::PointF());
2799 root
->SetDrawsContent(false);
2800 root
->SetIsContainerForFixedPositionLayers(true);
2801 root_clip
->SetHasRenderSurface(true);
2802 outer_clip
->SetBounds(outer_viewport_size
);
2803 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
2804 outer_scroll
->SetBounds(scroll_layer_size
);
2805 outer_scroll
->SetPosition(gfx::PointF());
2806 outer_scroll
->SetDrawsContent(false);
2807 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
2809 int inner_viewport_scroll_layer_id
= root
->id();
2810 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
2811 int page_scale_layer_id
= page_scale
->id();
2813 outer_clip
->AddChild(outer_scroll
.Pass());
2814 root
->AddChild(outer_clip
.Pass());
2815 page_scale
->AddChild(root
.Pass());
2816 root_clip
->AddChild(page_scale
.Pass());
2818 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2819 host_impl_
->active_tree()->SetViewportLayersFromIds(
2820 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2821 outer_viewport_scroll_layer_id
);
2823 host_impl_
->SetViewportSize(inner_viewport_size
);
2824 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2825 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
2829 gfx::Size layer_size_
;
2830 gfx::Size clip_size_
;
2831 gfx::Size viewport_size_
;
2832 float top_controls_height_
;
2834 LayerTreeSettings settings_
;
2835 }; // class LayerTreeHostImplTopControlsTest
2837 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
2838 SetupTopControlsAndScrollLayerWithVirtualViewport(
2839 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2842 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2843 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2845 // Make the test scroll delta a fractional amount, to verify that the
2846 // fixed container size delta is (1) non-zero, and (2) fractional, and
2847 // (3) matches the movement of the top controls.
2848 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
2849 host_impl_
->top_controls_manager()->ScrollBegin();
2850 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2851 host_impl_
->top_controls_manager()->ScrollEnd();
2853 LayerImpl
* inner_viewport_scroll_layer
=
2854 host_impl_
->active_tree()->InnerViewportScrollLayer();
2855 DCHECK(inner_viewport_scroll_layer
);
2856 host_impl_
->ScrollEnd();
2857 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
2858 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
2861 // In this test, the outer viewport is initially unscrollable. We test that a
2862 // scroll initiated on the inner viewport, causing the top controls to show and
2863 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2864 TEST_F(LayerTreeHostImplTopControlsTest
,
2865 TopControlsOuterViewportBecomesScrollable
) {
2866 SetupTopControlsAndScrollLayerWithVirtualViewport(
2867 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2870 LayerImpl
* inner_scroll
=
2871 host_impl_
->active_tree()->InnerViewportScrollLayer();
2872 LayerImpl
* inner_container
=
2873 host_impl_
->active_tree()->InnerViewportContainerLayer();
2874 LayerImpl
* outer_scroll
=
2875 host_impl_
->active_tree()->OuterViewportScrollLayer();
2876 LayerImpl
* outer_container
=
2877 host_impl_
->active_tree()->OuterViewportContainerLayer();
2879 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2880 outer_scroll
->SetDrawsContent(true);
2881 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
2883 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2884 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2885 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
2887 // The entire scroll delta should have been used to hide the top controls.
2888 // The viewport layers should be resized back to their full sizes.
2889 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2890 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2891 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
2892 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
2894 // The inner viewport should be scrollable by 50px * page_scale.
2895 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
2896 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
2897 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2898 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
2900 host_impl_
->ScrollEnd();
2902 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2903 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2904 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
2906 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2908 // The entire scroll delta should have been used to show the top controls.
2909 // The outer viewport should be resized to accomodate and scrolled to the
2910 // bottom of the document to keep the viewport in place.
2911 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2912 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
2913 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
2914 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
2915 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2917 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2918 // since it wasn't scrollable when the scroll began.
2919 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
2920 EXPECT_EQ(15.f
, outer_scroll
->CurrentScrollOffset().y());
2921 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2923 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
2924 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2925 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2927 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2928 host_impl_
->ScrollEnd();
2930 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2931 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2934 // Test that the fixed position container delta is appropriately adjusted
2935 // by the top controls showing/hiding and page scale doesn't affect it.
2936 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
2937 SetupTopControlsAndScrollLayerWithVirtualViewport(
2938 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2941 float page_scale
= 1.5f
;
2942 LayerImpl
* outer_viewport_scroll_layer
=
2943 host_impl_
->active_tree()->OuterViewportScrollLayer();
2945 // Zoom in, since the fixed container is the outer viewport, the delta should
2947 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
2949 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2950 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2952 // Scroll down, the top controls hiding should expand the viewport size so
2953 // the delta should be equal to the scroll distance.
2954 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
2955 host_impl_
->top_controls_manager()->ScrollBegin();
2956 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2957 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
2958 host_impl_
->top_controls_manager()->ContentTopOffset());
2959 EXPECT_VECTOR_EQ(top_controls_scroll_delta
,
2960 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2961 host_impl_
->ScrollEnd();
2963 // Scroll past the maximum extent. The delta shouldn't be greater than the
2964 // top controls height.
2965 host_impl_
->top_controls_manager()->ScrollBegin();
2966 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2967 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2968 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2969 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2970 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
2971 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2972 host_impl_
->ScrollEnd();
2974 // Scroll in the direction to make the top controls show.
2975 host_impl_
->top_controls_manager()->ScrollBegin();
2976 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
2977 EXPECT_EQ(top_controls_scroll_delta
.y(),
2978 host_impl_
->top_controls_manager()->ContentTopOffset());
2980 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
2981 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2982 host_impl_
->top_controls_manager()->ScrollEnd();
2985 // Test that if a scrollable sublayer doesn't consume the scroll,
2986 // top controls should hide when scrolling down.
2987 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
2988 gfx::Size
sub_content_size(100, 400);
2989 gfx::Size
sub_content_layer_size(100, 300);
2990 SetupTopControlsAndScrollLayerWithVirtualViewport(
2991 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
2994 // Show top controls
2995 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2997 LayerImpl
* outer_viewport_scroll_layer
=
2998 host_impl_
->active_tree()->OuterViewportScrollLayer();
2999 int id
= outer_viewport_scroll_layer
->id();
3001 scoped_ptr
<LayerImpl
> child
=
3002 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
3003 scoped_ptr
<LayerImpl
> child_clip
=
3004 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
3006 child_clip
->SetBounds(sub_content_layer_size
);
3007 child
->SetScrollClipLayer(child_clip
->id());
3008 child
->SetBounds(sub_content_size
);
3009 child
->SetPosition(gfx::PointF());
3010 child
->SetDrawsContent(true);
3011 child
->SetIsContainerForFixedPositionLayers(true);
3013 // scroll child to limit
3014 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
3015 child_clip
->AddChild(child
.Pass());
3016 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
3018 // Scroll 25px to hide top controls
3019 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3020 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3021 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3022 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3023 host_impl_
->ScrollEnd();
3025 // Top controls should be hidden
3026 EXPECT_EQ(scroll_delta
.y(),
3027 top_controls_height_
-
3028 host_impl_
->top_controls_manager()->ContentTopOffset());
3031 // Ensure setting the top controls position explicitly using the setters on the
3032 // TreeImpl correctly affects the top controls manager and viewport bounds.
3033 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
3034 CreateHostImpl(settings_
, CreateOutputSurface());
3035 SetupTopControlsAndScrollLayer();
3038 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3039 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3040 30.f
/ top_controls_height_
);
3041 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3042 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3043 EXPECT_FLOAT_EQ(-20.f
,
3044 host_impl_
->top_controls_manager()->ControlsTopOffset());
3046 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3047 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3048 EXPECT_FLOAT_EQ(-50.f
,
3049 host_impl_
->top_controls_manager()->ControlsTopOffset());
3051 host_impl_
->DidChangeTopControlsPosition();
3053 // Now that top controls have moved, expect the clip to resize.
3054 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3055 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3058 // Test that the top_controls delta and sent delta are appropriately
3059 // applied on sync tree activation. The total top controls offset shouldn't
3060 // change after the activation.
3061 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
3062 CreateHostImpl(settings_
, CreateOutputSurface());
3063 SetupTopControlsAndScrollLayer();
3066 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3067 20.f
/ top_controls_height_
);
3068 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3069 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
3070 15.f
/ top_controls_height_
);
3071 host_impl_
->active_tree()
3072 ->top_controls_shown_ratio()
3073 ->PullDeltaForMainThread();
3074 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3075 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
3076 top_controls_height_
);
3078 host_impl_
->DidChangeTopControlsPosition();
3079 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3080 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3081 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3083 host_impl_
->ActivateSyncTree();
3085 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3086 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3087 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3090 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
3091 top_controls_height_
);
3094 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3095 top_controls_height_
);
3098 // Test that changing the top controls layout height is correctly applied to
3099 // the inner viewport container bounds. That is, the top controls layout
3100 // height is the amount that the inner viewport container was shrunk outside
3101 // the compositor to accommodate the top controls.
3102 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
3103 CreateHostImpl(settings_
, CreateOutputSurface());
3104 SetupTopControlsAndScrollLayer();
3107 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
3108 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3110 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3112 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3113 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3115 host_impl_
->DidChangeTopControlsPosition();
3116 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3117 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3118 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3120 host_impl_
->sync_tree()->root_layer()->SetBounds(
3121 gfx::Size(root_clip_ptr
->bounds().width(),
3122 root_clip_ptr
->bounds().height() - 50.f
));
3124 host_impl_
->ActivateSyncTree();
3126 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3127 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3129 // The total bounds should remain unchanged since the bounds delta should
3130 // account for the difference between the layout height and the current
3131 // top controls offset.
3132 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3133 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), root_clip_ptr
->bounds_delta());
3135 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3136 host_impl_
->DidChangeTopControlsPosition();
3138 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
3139 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
3140 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3141 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), root_clip_ptr
->bounds_delta());
3142 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
3143 root_clip_ptr
->bounds());
3146 // Test that showing/hiding the top controls when the viewport is fully scrolled
3147 // doesn't incorrectly change the viewport offset due to clamping from changing
3149 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
3150 SetupTopControlsAndScrollLayerWithVirtualViewport(
3151 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3154 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3156 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3157 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3159 // Scroll the viewports to max scroll offset.
3160 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3161 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3163 gfx::ScrollOffset viewport_offset
=
3164 host_impl_
->active_tree()->TotalScrollOffset();
3165 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
3167 // Hide the top controls by 25px.
3168 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3169 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3170 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3171 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3173 // scrolling down at the max extents no longer hides the top controls
3174 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3176 // forcefully hide the top controls by 25px
3177 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3178 host_impl_
->ScrollEnd();
3180 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3181 top_controls_height_
-
3182 host_impl_
->top_controls_manager()->ContentTopOffset());
3184 inner_scroll
->ClampScrollToMaxScrollOffset();
3185 outer_scroll
->ClampScrollToMaxScrollOffset();
3187 // We should still be fully scrolled.
3188 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3189 host_impl_
->active_tree()->TotalScrollOffset());
3191 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3193 // Bring the top controls down by 25px.
3194 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3195 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3196 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3197 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3198 host_impl_
->ScrollEnd();
3200 // The viewport offset shouldn't have changed.
3201 EXPECT_EQ(viewport_offset
,
3202 host_impl_
->active_tree()->TotalScrollOffset());
3204 // Scroll the viewports to max scroll offset.
3205 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3206 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3207 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3208 host_impl_
->active_tree()->TotalScrollOffset());
3211 // Test that the top controls coming in and out maintains the same aspect ratio
3212 // between the inner and outer viewports.
3213 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3214 SetupTopControlsAndScrollLayerWithVirtualViewport(
3215 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3218 EXPECT_FLOAT_EQ(top_controls_height_
,
3219 host_impl_
->top_controls_manager()->ContentTopOffset());
3221 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3222 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3223 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3224 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3225 host_impl_
->ScrollEnd();
3227 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3228 top_controls_height_
-
3229 host_impl_
->top_controls_manager()->ContentTopOffset());
3231 // Top controls were hidden by 25px so the inner viewport should have expanded
3233 LayerImpl
* outer_container
=
3234 host_impl_
->active_tree()->OuterViewportContainerLayer();
3235 LayerImpl
* inner_container
=
3236 host_impl_
->active_tree()->InnerViewportContainerLayer();
3237 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3239 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3240 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3241 inner_container
->BoundsForScrolling().height();
3242 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3243 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3245 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3248 // Test that scrolling the outer viewport affects the top controls.
3249 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3250 SetupTopControlsAndScrollLayerWithVirtualViewport(
3251 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3254 EXPECT_EQ(top_controls_height_
,
3255 host_impl_
->top_controls_manager()->ContentTopOffset());
3257 // Send a gesture scroll that will scroll the outer viewport, make sure the
3258 // top controls get scrolled.
3259 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3260 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3261 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3262 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3263 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3264 host_impl_
->CurrentlyScrollingLayer());
3265 host_impl_
->ScrollEnd();
3267 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3268 top_controls_height_
-
3269 host_impl_
->top_controls_manager()->ContentTopOffset());
3271 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3272 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3273 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3274 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3276 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3277 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3278 host_impl_
->CurrentlyScrollingLayer());
3280 host_impl_
->ScrollEnd();
3282 // Position the viewports such that the inner viewport will be scrolled.
3283 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3284 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3285 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3287 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3288 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3289 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3290 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3292 EXPECT_EQ(top_controls_height_
,
3293 host_impl_
->top_controls_manager()->ContentTopOffset());
3295 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3296 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3298 host_impl_
->ScrollEnd();
3301 TEST_F(LayerTreeHostImplTopControlsTest
,
3302 ScrollNonScrollableRootWithTopControls
) {
3303 CreateHostImpl(settings_
, CreateOutputSurface());
3304 SetupTopControlsAndScrollLayer();
3307 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3308 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3310 host_impl_
->top_controls_manager()->ScrollBegin();
3311 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3312 host_impl_
->top_controls_manager()->ScrollEnd();
3313 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3314 // Now that top controls have moved, expect the clip to resize.
3315 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3316 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3318 host_impl_
->ScrollEnd();
3320 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3321 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3323 float scroll_increment_y
= -25.f
;
3324 host_impl_
->top_controls_manager()->ScrollBegin();
3325 host_impl_
->top_controls_manager()->ScrollBy(
3326 gfx::Vector2dF(0.f
, scroll_increment_y
));
3327 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3328 host_impl_
->top_controls_manager()->ContentTopOffset());
3329 // Now that top controls have moved, expect the clip to resize.
3330 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3331 viewport_size_
.height() + scroll_increment_y
),
3332 root_clip_ptr
->bounds());
3334 host_impl_
->top_controls_manager()->ScrollBy(
3335 gfx::Vector2dF(0.f
, scroll_increment_y
));
3336 host_impl_
->top_controls_manager()->ScrollEnd();
3337 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3338 host_impl_
->top_controls_manager()->ContentTopOffset());
3339 // Now that top controls have moved, expect the clip to resize.
3340 EXPECT_EQ(clip_size_
, root_clip_ptr
->bounds());
3342 host_impl_
->ScrollEnd();
3344 // Verify the layer is once-again non-scrollable.
3346 gfx::ScrollOffset(),
3347 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3349 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3350 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3353 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3354 // Test the configuration where a non-composited root layer is embedded in a
3355 // scrollable outer layer.
3356 gfx::Size
surface_size(10, 10);
3357 gfx::Size
contents_size(20, 20);
3359 scoped_ptr
<LayerImpl
> content_layer
=
3360 LayerImpl::Create(host_impl_
->active_tree(), 1);
3361 content_layer
->SetDrawsContent(true);
3362 content_layer
->SetPosition(gfx::PointF());
3363 content_layer
->SetBounds(contents_size
);
3365 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3366 LayerImpl::Create(host_impl_
->active_tree(), 3);
3367 scroll_clip_layer
->SetBounds(surface_size
);
3369 scoped_ptr
<LayerImpl
> scroll_layer
=
3370 LayerImpl::Create(host_impl_
->active_tree(), 2);
3371 scroll_layer
->SetScrollClipLayer(3);
3372 scroll_layer
->SetBounds(contents_size
);
3373 scroll_layer
->SetPosition(gfx::PointF());
3374 scroll_layer
->AddChild(content_layer
.Pass());
3375 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3377 scroll_clip_layer
->SetHasRenderSurface(true);
3378 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3379 host_impl_
->SetViewportSize(surface_size
);
3382 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3383 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3384 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3385 host_impl_
->ScrollEnd();
3386 EXPECT_TRUE(did_request_redraw_
);
3387 EXPECT_TRUE(did_request_commit_
);
3390 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3391 gfx::Size
surface_size(10, 10);
3392 gfx::Size
contents_size(20, 20);
3393 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3394 root
->SetBounds(surface_size
);
3395 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3396 root
->SetHasRenderSurface(true);
3397 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3398 host_impl_
->SetViewportSize(surface_size
);
3401 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3402 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3403 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3404 host_impl_
->ScrollEnd();
3405 EXPECT_TRUE(did_request_redraw_
);
3406 EXPECT_TRUE(did_request_commit_
);
3409 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3410 gfx::Size
surface_size(10, 10);
3411 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3412 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3413 root
->SetHasRenderSurface(true);
3414 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3415 host_impl_
->SetViewportSize(surface_size
);
3418 // Scroll event is ignored because the input coordinate is outside the layer
3420 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3421 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3422 EXPECT_FALSE(did_request_redraw_
);
3423 EXPECT_FALSE(did_request_commit_
);
3426 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3427 gfx::Size
surface_size(10, 10);
3428 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3429 root
->SetHasRenderSurface(true);
3430 scoped_ptr
<LayerImpl
> child
=
3431 CreateScrollableLayer(2, surface_size
, root
.get());
3432 host_impl_
->SetViewportSize(surface_size
);
3434 gfx::Transform matrix
;
3435 matrix
.RotateAboutXAxis(180.0);
3436 child
->SetTransform(matrix
);
3437 child
->SetDoubleSided(false);
3439 root
->AddChild(child
.Pass());
3440 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3443 // Scroll event is ignored because the scrollable layer is not facing the
3444 // viewer and there is nothing scrollable behind it.
3445 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3446 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3447 EXPECT_FALSE(did_request_redraw_
);
3448 EXPECT_FALSE(did_request_commit_
);
3451 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3452 gfx::Size
surface_size(10, 10);
3453 scoped_ptr
<LayerImpl
> clip_layer
=
3454 LayerImpl::Create(host_impl_
->active_tree(), 3);
3455 scoped_ptr
<LayerImpl
> content_layer
=
3456 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3457 content_layer
->SetShouldScrollOnMainThread(true);
3458 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3460 // Note: we can use the same clip layer for both since both calls to
3461 // CreateScrollableLayer() use the same surface size.
3462 scoped_ptr
<LayerImpl
> scroll_layer
=
3463 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3464 scroll_layer
->AddChild(content_layer
.Pass());
3465 clip_layer
->AddChild(scroll_layer
.Pass());
3466 clip_layer
->SetHasRenderSurface(true);
3468 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3469 host_impl_
->SetViewportSize(surface_size
);
3472 // Scrolling fails because the content layer is asking to be scrolled on the
3474 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3475 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3478 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3479 gfx::Size
surface_size(20, 20);
3480 gfx::Size
viewport_size(10, 10);
3481 float page_scale
= 2.f
;
3482 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3483 scoped_ptr
<LayerImpl
> root_clip
=
3484 LayerImpl::Create(host_impl_
->active_tree(), 2);
3485 scoped_ptr
<LayerImpl
> root_scrolling
=
3486 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3487 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3488 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3489 root_clip
->AddChild(root_scrolling
.Pass());
3490 root
->AddChild(root_clip
.Pass());
3491 root
->SetHasRenderSurface(true);
3492 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3493 // The behaviour in this test assumes the page scale is applied at a layer
3494 // above the clip layer.
3495 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3497 host_impl_
->active_tree()->DidBecomeActive();
3498 host_impl_
->SetViewportSize(viewport_size
);
3501 LayerImpl
* root_scroll
=
3502 host_impl_
->active_tree()->InnerViewportScrollLayer();
3503 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3505 gfx::Vector2d
scroll_delta(0, 10);
3506 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3507 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3508 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3509 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3510 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3511 host_impl_
->ScrollEnd();
3513 // Set new page scale from main thread.
3514 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, page_scale
,
3517 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3518 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3519 expected_scroll_delta
));
3521 // The scroll range should also have been updated.
3522 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3524 // The page scale delta remains constant because the impl thread did not
3526 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3529 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3530 gfx::Size
surface_size(20, 20);
3531 gfx::Size
viewport_size(10, 10);
3532 float page_scale
= 2.f
;
3533 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3534 scoped_ptr
<LayerImpl
> root_clip
=
3535 LayerImpl::Create(host_impl_
->active_tree(), 2);
3536 scoped_ptr
<LayerImpl
> root_scrolling
=
3537 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3538 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3539 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3540 root_clip
->AddChild(root_scrolling
.Pass());
3541 root
->AddChild(root_clip
.Pass());
3542 root
->SetHasRenderSurface(true);
3543 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3544 // The behaviour in this test assumes the page scale is applied at a layer
3545 // above the clip layer.
3546 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3548 host_impl_
->active_tree()->DidBecomeActive();
3549 host_impl_
->SetViewportSize(viewport_size
);
3550 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, page_scale
);
3553 LayerImpl
* root_scroll
=
3554 host_impl_
->active_tree()->InnerViewportScrollLayer();
3555 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3557 gfx::Vector2d
scroll_delta(0, 10);
3558 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3559 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3560 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3561 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3562 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3563 host_impl_
->ScrollEnd();
3565 // Set new page scale on impl thread by pinching.
3566 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3567 host_impl_
->PinchGestureBegin();
3568 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3569 host_impl_
->PinchGestureEnd();
3570 host_impl_
->ScrollEnd();
3573 // The scroll delta is not scaled because the main thread did not scale.
3574 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3575 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3576 expected_scroll_delta
));
3578 // The scroll range should also have been updated.
3579 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3581 // The page scale delta should match the new scale on the impl side.
3582 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3585 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3586 gfx::Size
surface_size(10, 10);
3587 float default_page_scale
= 1.f
;
3588 gfx::Transform default_page_scale_matrix
;
3589 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3591 float new_page_scale
= 2.f
;
3592 gfx::Transform new_page_scale_matrix
;
3593 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3595 // Create a normal scrollable root layer and another scrollable child layer.
3596 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3597 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3598 LayerImpl
* child
= scroll
->children()[0];
3600 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3601 LayerImpl::Create(host_impl_
->active_tree(), 6);
3602 scoped_ptr
<LayerImpl
> scrollable_child
=
3603 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3604 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3605 child
->AddChild(scrollable_child_clip
.Pass());
3606 LayerImpl
* grand_child
= child
->children()[0];
3608 // Set new page scale on impl thread by pinching.
3609 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3610 host_impl_
->PinchGestureBegin();
3611 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3612 host_impl_
->PinchGestureEnd();
3613 host_impl_
->ScrollEnd();
3616 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3617 // the page scale delta on the root layer is applied hierarchically.
3618 LayerTreeHostImpl::FrameData frame
;
3619 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3620 host_impl_
->DrawLayers(&frame
);
3621 host_impl_
->DidDrawAllLayers(frame
);
3623 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3624 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3625 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3626 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3627 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3628 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3629 EXPECT_EQ(new_page_scale
,
3630 grand_child
->draw_transform().matrix().getDouble(0, 0));
3631 EXPECT_EQ(new_page_scale
,
3632 grand_child
->draw_transform().matrix().getDouble(1, 1));
3635 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3636 gfx::Size
surface_size(30, 30);
3637 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3638 root
->SetBounds(gfx::Size(5, 5));
3639 root
->SetHasRenderSurface(true);
3640 scoped_ptr
<LayerImpl
> root_scrolling
=
3641 LayerImpl::Create(host_impl_
->active_tree(), 2);
3642 root_scrolling
->SetBounds(surface_size
);
3643 root_scrolling
->SetScrollClipLayer(root
->id());
3644 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3645 LayerImpl
* root_scrolling_ptr
= root_scrolling
.get();
3646 root
->AddChild(root_scrolling
.Pass());
3647 int child_scroll_layer_id
= 3;
3648 scoped_ptr
<LayerImpl
> child_scrolling
= CreateScrollableLayer(
3649 child_scroll_layer_id
, surface_size
, root_scrolling_ptr
);
3650 LayerImpl
* child
= child_scrolling
.get();
3651 root_scrolling_ptr
->AddChild(child_scrolling
.Pass());
3652 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3653 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3655 host_impl_
->active_tree()->DidBecomeActive();
3656 host_impl_
->SetViewportSize(surface_size
);
3659 gfx::Vector2d
scroll_delta(0, 10);
3660 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3661 gfx::ScrollOffset
expected_max_scroll(child
->MaxScrollOffset());
3662 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3663 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3664 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3665 host_impl_
->ScrollEnd();
3667 float page_scale
= 2.f
;
3668 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3673 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3674 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_scroll_layer_id
,
3675 expected_scroll_delta
));
3677 // The scroll range should not have changed.
3678 EXPECT_EQ(child
->MaxScrollOffset(), expected_max_scroll
);
3680 // The page scale delta remains constant because the impl thread did not
3682 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3685 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
3686 // Scroll a child layer beyond its maximum scroll range and make sure the
3687 // parent layer is scrolled on the axis on which the child was unable to
3689 gfx::Size
surface_size(10, 10);
3690 gfx::Size
content_size(20, 20);
3691 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3692 root
->SetBounds(surface_size
);
3693 root
->SetHasRenderSurface(true);
3694 scoped_ptr
<LayerImpl
> grand_child
=
3695 CreateScrollableLayer(3, content_size
, root
.get());
3697 scoped_ptr
<LayerImpl
> child
=
3698 CreateScrollableLayer(2, content_size
, root
.get());
3699 LayerImpl
* grand_child_layer
= grand_child
.get();
3700 child
->AddChild(grand_child
.Pass());
3702 LayerImpl
* child_layer
= child
.get();
3703 root
->AddChild(child
.Pass());
3704 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3705 host_impl_
->active_tree()->DidBecomeActive();
3706 host_impl_
->SetViewportSize(surface_size
);
3707 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3708 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3712 gfx::Vector2d
scroll_delta(-8, -7);
3713 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3714 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3715 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3716 host_impl_
->ScrollEnd();
3718 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3719 host_impl_
->ProcessScrollDeltas();
3721 // The grand child should have scrolled up to its limit.
3722 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
3723 LayerImpl
* grand_child
= child
->children()[0];
3724 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3725 gfx::Vector2d(0, -5)));
3727 // The child should have only scrolled on the other axis.
3728 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
3729 gfx::Vector2d(-3, 0)));
3733 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
3734 // Scroll a child layer beyond its maximum scroll range and make sure the
3735 // the scroll doesn't bubble up to the parent layer.
3736 gfx::Size
surface_size(20, 20);
3737 gfx::Size
viewport_size(10, 10);
3738 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3739 root
->SetHasRenderSurface(true);
3740 scoped_ptr
<LayerImpl
> root_scrolling
=
3741 CreateScrollableLayer(2, surface_size
, root
.get());
3742 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3744 scoped_ptr
<LayerImpl
> grand_child
=
3745 CreateScrollableLayer(4, surface_size
, root
.get());
3747 scoped_ptr
<LayerImpl
> child
=
3748 CreateScrollableLayer(3, surface_size
, root
.get());
3749 LayerImpl
* grand_child_layer
= grand_child
.get();
3750 child
->AddChild(grand_child
.Pass());
3752 LayerImpl
* child_layer
= child
.get();
3753 root_scrolling
->AddChild(child
.Pass());
3754 root
->AddChild(root_scrolling
.Pass());
3755 EXPECT_EQ(viewport_size
, root
->bounds());
3756 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3757 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3759 host_impl_
->active_tree()->DidBecomeActive();
3760 host_impl_
->SetViewportSize(viewport_size
);
3762 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3763 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3767 gfx::Vector2d
scroll_delta(0, -10);
3768 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3769 host_impl_
->ScrollBegin(gfx::Point(),
3770 InputHandler::NON_BUBBLING_GESTURE
));
3771 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3772 host_impl_
->ScrollEnd();
3774 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3775 host_impl_
->ProcessScrollDeltas();
3777 // The grand child should have scrolled up to its limit.
3779 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
3780 LayerImpl
* grand_child
= child
->children()[0];
3781 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3782 gfx::Vector2d(0, -2)));
3784 // The child should not have scrolled.
3785 ExpectNone(*scroll_info
.get(), child
->id());
3787 // The next time we scroll we should only scroll the parent.
3788 scroll_delta
= gfx::Vector2d(0, -3);
3789 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3790 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3791 InputHandler::NON_BUBBLING_GESTURE
));
3792 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3793 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3794 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
3795 host_impl_
->ScrollEnd();
3797 scroll_info
= host_impl_
->ProcessScrollDeltas();
3799 // The child should have scrolled up to its limit.
3800 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
3801 gfx::Vector2d(0, -3)));
3803 // The grand child should not have scrolled.
3804 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3805 gfx::Vector2d(0, -2)));
3807 // After scrolling the parent, another scroll on the opposite direction
3808 // should still scroll the child.
3809 scroll_delta
= gfx::Vector2d(0, 7);
3810 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3811 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3812 InputHandler::NON_BUBBLING_GESTURE
));
3813 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3814 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3815 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3816 host_impl_
->ScrollEnd();
3818 scroll_info
= host_impl_
->ProcessScrollDeltas();
3820 // The grand child should have scrolled.
3821 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3822 gfx::Vector2d(0, 5)));
3824 // The child should not have scrolled.
3825 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
3826 gfx::Vector2d(0, -3)));
3828 // Scrolling should be adjusted from viewport space.
3829 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
3830 host_impl_
->SetPageScaleOnActiveTree(2.f
);
3832 scroll_delta
= gfx::Vector2d(0, -2);
3833 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3834 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3835 InputHandler::NON_BUBBLING_GESTURE
));
3836 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
3837 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3838 host_impl_
->ScrollEnd();
3840 scroll_info
= host_impl_
->ProcessScrollDeltas();
3842 // Should have scrolled by half the amount in layer space (5 - 2/2)
3843 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
3844 gfx::Vector2d(0, 4)));
3847 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
3848 // When we try to scroll a non-scrollable child layer, the scroll delta
3849 // should be applied to one of its ancestors if possible.
3850 gfx::Size
surface_size(10, 10);
3851 gfx::Size
content_size(20, 20);
3852 scoped_ptr
<LayerImpl
> root_clip
=
3853 LayerImpl::Create(host_impl_
->active_tree(), 3);
3854 root_clip
->SetHasRenderSurface(true);
3855 scoped_ptr
<LayerImpl
> root
=
3856 CreateScrollableLayer(1, content_size
, root_clip
.get());
3857 // Make 'root' the clip layer for child: since they have the same sizes the
3858 // child will have zero max_scroll_offset and scrolls will bubble.
3859 scoped_ptr
<LayerImpl
> child
=
3860 CreateScrollableLayer(2, content_size
, root
.get());
3861 child
->SetIsContainerForFixedPositionLayers(true);
3862 root
->SetBounds(content_size
);
3864 int root_scroll_id
= root
->id();
3865 root
->AddChild(child
.Pass());
3866 root_clip
->AddChild(root
.Pass());
3868 host_impl_
->SetViewportSize(surface_size
);
3869 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3870 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
3872 host_impl_
->active_tree()->DidBecomeActive();
3875 gfx::Vector2d
scroll_delta(0, 4);
3876 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3877 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3878 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3879 host_impl_
->ScrollEnd();
3881 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3882 host_impl_
->ProcessScrollDeltas();
3884 // Only the root scroll should have scrolled.
3885 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
3887 ScrollInfoContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
));
3891 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
3892 gfx::Size
surface_size(10, 10);
3893 scoped_ptr
<LayerImpl
> root_clip
=
3894 LayerImpl::Create(host_impl_
->active_tree(), 1);
3895 scoped_ptr
<LayerImpl
> root_scroll
=
3896 CreateScrollableLayer(2, surface_size
, root_clip
.get());
3897 root_scroll
->SetIsContainerForFixedPositionLayers(true);
3898 root_clip
->SetHasRenderSurface(true);
3899 root_clip
->AddChild(root_scroll
.Pass());
3900 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3901 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3903 host_impl_
->active_tree()->DidBecomeActive();
3904 host_impl_
->SetViewportSize(surface_size
);
3906 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3909 host_impl_
->active_tree()->DetachLayerTree();
3910 scoped_ptr
<LayerImpl
> root_clip2
=
3911 LayerImpl::Create(host_impl_
->active_tree(), 3);
3912 scoped_ptr
<LayerImpl
> root_scroll2
=
3913 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
3914 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
3915 root_clip2
->AddChild(root_scroll2
.Pass());
3916 root_clip2
->SetHasRenderSurface(true);
3917 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
3918 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
3920 host_impl_
->active_tree()->DidBecomeActive();
3922 // Scrolling should still work even though we did not draw yet.
3923 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3924 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3927 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
3928 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3930 // Rotate the root layer 90 degrees counter-clockwise about its center.
3931 gfx::Transform rotate_transform
;
3932 rotate_transform
.Rotate(-90.0);
3933 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
3935 gfx::Size
surface_size(50, 50);
3936 host_impl_
->SetViewportSize(surface_size
);
3939 // Scroll to the right in screen coordinates with a gesture.
3940 gfx::Vector2d
gesture_scroll_delta(10, 0);
3941 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3942 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3943 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3944 host_impl_
->ScrollEnd();
3946 // The layer should have scrolled down in its local coordinates.
3947 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3948 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
3949 gfx::Vector2d(0, gesture_scroll_delta
.x())));
3951 // Reset and scroll down with the wheel.
3952 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3953 gfx::Vector2d
wheel_scroll_delta(0, 10);
3954 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3955 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3956 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3957 host_impl_
->ScrollEnd();
3959 // The layer should have scrolled down in its local coordinates.
3960 scroll_info
= host_impl_
->ProcessScrollDeltas();
3961 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
3962 wheel_scroll_delta
));
3965 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
3966 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3967 int child_clip_layer_id
= 6;
3968 int child_layer_id
= 7;
3969 float child_layer_angle
= -20.f
;
3971 // Create a child layer that is rotated to a non-axis-aligned angle.
3972 scoped_ptr
<LayerImpl
> clip_layer
=
3973 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
3974 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
3975 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
3976 gfx::Transform rotate_transform
;
3977 rotate_transform
.Translate(-50.0, -50.0);
3978 rotate_transform
.Rotate(child_layer_angle
);
3979 rotate_transform
.Translate(50.0, 50.0);
3980 clip_layer
->SetTransform(rotate_transform
);
3982 // Only allow vertical scrolling.
3983 clip_layer
->SetBounds(
3984 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
3985 // The rotation depends on the layer's transform origin, and the child layer
3986 // is a different size than the clip, so make sure the clip layer's origin
3987 // lines up over the child.
3988 clip_layer
->SetTransformOrigin(gfx::Point3F(
3989 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
3990 LayerImpl
* child_ptr
= child
.get();
3991 clip_layer
->AddChild(child
.Pass());
3992 scroll_layer
->AddChild(clip_layer
.Pass());
3994 gfx::Size
surface_size(50, 50);
3995 host_impl_
->SetViewportSize(surface_size
);
3998 // Scroll down in screen coordinates with a gesture.
3999 gfx::Vector2d
gesture_scroll_delta(0, 10);
4000 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4001 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4002 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4003 host_impl_
->ScrollEnd();
4005 // The child layer should have scrolled down in its local coordinates an
4006 // amount proportional to the angle between it and the input scroll delta.
4007 gfx::Vector2d
expected_scroll_delta(
4008 0, gesture_scroll_delta
.y() *
4009 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
4010 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4011 host_impl_
->ProcessScrollDeltas();
4012 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4013 expected_scroll_delta
));
4015 // The root scroll layer should not have scrolled, because the input delta
4016 // was close to the layer's axis of movement.
4017 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4020 // Now reset and scroll the same amount horizontally.
4021 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4022 gfx::Vector2d
gesture_scroll_delta(10, 0);
4023 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4024 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4025 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4026 host_impl_
->ScrollEnd();
4028 // The child layer should have scrolled down in its local coordinates an
4029 // amount proportional to the angle between it and the input scroll delta.
4030 gfx::Vector2d
expected_scroll_delta(
4031 0, -gesture_scroll_delta
.x() *
4032 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
4033 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4034 host_impl_
->ProcessScrollDeltas();
4035 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4036 expected_scroll_delta
));
4038 // The root scroll layer should have scrolled more, since the input scroll
4039 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4040 gfx::Vector2d
expected_root_scroll_delta(
4041 gesture_scroll_delta
.x() *
4042 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
4044 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4045 expected_root_scroll_delta
));
4049 TEST_F(LayerTreeHostImplTest
, ScrollPerspectiveTransformedLayer
) {
4050 // When scrolling an element with perspective, the distance scrolled
4051 // depends on the point at which the scroll begins.
4052 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4053 int child_clip_layer_id
= 6;
4054 int child_layer_id
= 7;
4056 // Create a child layer that is rotated on its x axis, with perspective.
4057 scoped_ptr
<LayerImpl
> clip_layer
=
4058 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4059 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4060 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4061 LayerImpl
* child_ptr
= child
.get();
4062 gfx::Transform perspective_transform
;
4063 perspective_transform
.Translate(-50.0, -50.0);
4064 perspective_transform
.ApplyPerspectiveDepth(20);
4065 perspective_transform
.RotateAboutXAxis(45);
4066 perspective_transform
.Translate(50.0, 50.0);
4067 clip_layer
->SetTransform(perspective_transform
);
4069 clip_layer
->SetBounds(gfx::Size(child_ptr
->bounds().width() / 2,
4070 child_ptr
->bounds().height() / 2));
4071 // The transform depends on the layer's transform origin, and the child layer
4072 // is a different size than the clip, so make sure the clip layer's origin
4073 // lines up over the child.
4074 clip_layer
->SetTransformOrigin(gfx::Point3F(
4075 clip_layer
->bounds().width(), clip_layer
->bounds().height(), 0.f
));
4076 clip_layer
->AddChild(child
.Pass());
4077 scroll_layer
->AddChild(clip_layer
.Pass());
4079 gfx::Size
surface_size(50, 50);
4080 host_impl_
->SetViewportSize(surface_size
);
4082 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
4084 gfx::Vector2d gesture_scroll_deltas
[4];
4085 gesture_scroll_deltas
[0] = gfx::Vector2d(4, 10);
4086 gesture_scroll_deltas
[1] = gfx::Vector2d(4, 10);
4087 gesture_scroll_deltas
[2] = gfx::Vector2d(10, 0);
4088 gesture_scroll_deltas
[3] = gfx::Vector2d(10, 0);
4090 gfx::Vector2d expected_scroll_deltas
[4];
4091 // Perspective affects the vertical delta by a different
4092 // amount depending on the vertical position of the |viewport_point|.
4093 expected_scroll_deltas
[0] = gfx::Vector2d(2, 8);
4094 expected_scroll_deltas
[1] = gfx::Vector2d(1, 4);
4095 // Deltas which start with the same vertical position of the
4096 // |viewport_point| are subject to identical perspective effects.
4097 expected_scroll_deltas
[2] = gfx::Vector2d(4, 0);
4098 expected_scroll_deltas
[3] = gfx::Vector2d(4, 0);
4100 gfx::Point
viewport_point(1, 1);
4102 // Scroll in screen coordinates with a gesture. Each scroll starts
4103 // where the previous scroll ended, but the scroll position is reset
4105 for (int i
= 0; i
< 4; ++i
) {
4106 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4108 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4109 host_impl_
->ScrollBegin(viewport_point
, InputHandler::GESTURE
));
4110 host_impl_
->ScrollBy(viewport_point
, gesture_scroll_deltas
[i
]);
4111 viewport_point
+= gesture_scroll_deltas
[i
];
4112 host_impl_
->ScrollEnd();
4114 scroll_info
= host_impl_
->ProcessScrollDeltas();
4115 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4116 expected_scroll_deltas
[i
]));
4118 // The root scroll layer should not have scrolled, because the input delta
4119 // was close to the layer's axis of movement.
4120 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4124 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
4125 LayerImpl
* scroll_layer
=
4126 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4128 // Scale the layer to twice its normal size.
4130 gfx::Transform scale_transform
;
4131 scale_transform
.Scale(scale
, scale
);
4132 scroll_layer
->SetTransform(scale_transform
);
4134 gfx::Size
surface_size(50, 50);
4135 host_impl_
->SetViewportSize(surface_size
);
4138 // Scroll down in screen coordinates with a gesture.
4139 gfx::Vector2d
scroll_delta(0, 10);
4140 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4141 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4142 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4143 host_impl_
->ScrollEnd();
4145 // The layer should have scrolled down in its local coordinates, but half the
4147 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4148 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4149 gfx::Vector2d(0, scroll_delta
.y() / scale
)));
4151 // Reset and scroll down with the wheel.
4152 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4153 gfx::Vector2d
wheel_scroll_delta(0, 10);
4154 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4155 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4156 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4157 host_impl_
->ScrollEnd();
4159 // It should apply the scale factor to the scroll delta for the wheel event.
4160 scroll_info
= host_impl_
->ProcessScrollDeltas();
4161 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4162 wheel_scroll_delta
));
4165 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
4169 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
4170 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
4171 gfx::Size(width
* scale
- 1, height
* scale
));
4172 host_impl_
->SetDeviceScaleFactor(scale
);
4173 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4175 LayerImpl
* inner_viewport_scroll_layer
=
4176 host_impl_
->active_tree()->InnerViewportScrollLayer();
4177 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4178 inner_viewport_scroll_layer
->MaxScrollOffset());
4181 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
4183 TestScrollOffsetDelegate()
4184 : page_scale_factor_(0.f
),
4185 min_page_scale_factor_(-1.f
),
4186 max_page_scale_factor_(-1.f
),
4187 needs_animate_(false) {}
4189 ~TestScrollOffsetDelegate() override
{}
4191 gfx::ScrollOffset
GetTotalScrollOffset() override
{
4192 return getter_return_value_
;
4195 bool IsExternalScrollActive() const override
{ return false; }
4197 void SetNeedsAnimate(const AnimationCallback
&) override
{
4198 needs_animate_
= true;
4201 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
4202 const gfx::ScrollOffset
& max_scroll_offset
,
4203 const gfx::SizeF
& scrollable_size
,
4204 float page_scale_factor
,
4205 float min_page_scale_factor
,
4206 float max_page_scale_factor
) override
{
4207 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
4208 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
4209 last_set_scroll_offset_
= total_scroll_offset
;
4210 max_scroll_offset_
= max_scroll_offset
;
4211 scrollable_size_
= scrollable_size
;
4212 page_scale_factor_
= page_scale_factor
;
4213 min_page_scale_factor_
= min_page_scale_factor
;
4214 max_page_scale_factor_
= max_page_scale_factor
;
4216 set_getter_return_value(last_set_scroll_offset_
);
4219 bool GetAndResetNeedsAnimate() {
4220 bool needs_animate
= needs_animate_
;
4221 needs_animate_
= false;
4222 return needs_animate
;
4225 gfx::ScrollOffset
last_set_scroll_offset() {
4226 return last_set_scroll_offset_
;
4229 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
4230 getter_return_value_
= value
;
4233 gfx::ScrollOffset
max_scroll_offset() const {
4234 return max_scroll_offset_
;
4237 gfx::SizeF
scrollable_size() const {
4238 return scrollable_size_
;
4241 float page_scale_factor() const {
4242 return page_scale_factor_
;
4245 float min_page_scale_factor() const {
4246 return min_page_scale_factor_
;
4249 float max_page_scale_factor() const {
4250 return max_page_scale_factor_
;
4254 gfx::ScrollOffset last_set_scroll_offset_
;
4255 gfx::ScrollOffset getter_return_value_
;
4256 gfx::ScrollOffset max_scroll_offset_
;
4257 gfx::SizeF scrollable_size_
;
4258 float page_scale_factor_
;
4259 float min_page_scale_factor_
;
4260 float max_page_scale_factor_
;
4261 bool needs_animate_
;
4264 // TODO(jdduke): Test root fling animation.
4265 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4266 TestScrollOffsetDelegate scroll_delegate
;
4267 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4268 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4269 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4270 clip_layer
->SetBounds(gfx::Size(10, 20));
4272 // Setting the delegate results in the current scroll offset being set.
4273 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4274 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4275 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4276 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4277 EXPECT_EQ(initial_scroll_delta
.ToString(),
4278 scroll_delegate
.last_set_scroll_offset().ToString());
4280 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4281 // page_scale_factor and {min|max}_page_scale_factor being set.
4282 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4283 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4284 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4285 EXPECT_EQ(0.f
, scroll_delegate
.min_page_scale_factor());
4286 EXPECT_EQ(0.f
, scroll_delegate
.max_page_scale_factor());
4288 // Updating page scale immediately updates the delegate.
4289 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4290 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4291 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4292 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4293 host_impl_
->SetPageScaleOnActiveTree(2.f
* 1.5f
);
4294 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
4295 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4296 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4297 host_impl_
->SetPageScaleOnActiveTree(2.f
);
4298 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4299 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4300 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4301 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4303 // The pinch gesture doesn't put the delegate into a state where the scroll
4304 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4306 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4307 host_impl_
->PinchGestureBegin();
4308 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4309 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4310 host_impl_
->PinchGestureEnd();
4311 host_impl_
->ScrollEnd();
4313 // Scrolling should be relative to the offset as returned by the delegate.
4314 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4315 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4317 scroll_delegate
.set_getter_return_value(current_offset
);
4318 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4319 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4320 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4322 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4323 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4324 scroll_delegate
.last_set_scroll_offset());
4326 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4327 scroll_delegate
.set_getter_return_value(current_offset
);
4328 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4329 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4330 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4331 scroll_delegate
.last_set_scroll_offset());
4332 host_impl_
->ScrollEnd();
4333 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
4334 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4336 // Forces a full tree synchronization and ensures that the scroll delegate
4337 // sees the correct size of the new tree.
4338 gfx::Size
new_size(42, 24);
4339 host_impl_
->CreatePendingTree();
4340 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4341 host_impl_
->ActivateSyncTree();
4342 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4344 // Un-setting the delegate should propagate the delegate's current offset to
4345 // the root scrollable layer.
4346 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4347 scroll_delegate
.set_getter_return_value(current_offset
);
4348 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4349 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4351 EXPECT_EQ(current_offset
.ToString(),
4352 scroll_layer
->CurrentScrollOffset().ToString());
4355 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4356 const gfx::Transform target_space_transform
=
4357 layer
->draw_properties().target_space_transform
;
4358 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4359 gfx::Point translated_point
;
4360 target_space_transform
.TransformPoint(&translated_point
);
4361 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4362 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4365 TEST_F(LayerTreeHostImplTest
,
4366 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4367 TestScrollOffsetDelegate scroll_delegate
;
4368 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4369 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4370 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4371 clip_layer
->SetBounds(gfx::Size(10, 20));
4372 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4374 // Draw first frame to clear any pending draws and check scroll.
4376 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4377 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4379 // Set external scroll delta on delegate and notify LayerTreeHost.
4380 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4381 scroll_delegate
.set_getter_return_value(scroll_offset
);
4382 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4384 // Check scroll delta reflected in layer.
4385 LayerTreeHostImpl::FrameData frame
;
4386 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4387 host_impl_
->DrawLayers(&frame
);
4388 host_impl_
->DidDrawAllLayers(frame
);
4389 EXPECT_FALSE(frame
.has_no_damage
);
4390 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4392 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4395 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4396 InputHandlerScrollResult scroll_result
;
4397 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4398 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4399 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4401 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4403 // In-bounds scrolling does not affect overscroll.
4404 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4405 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4406 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4407 EXPECT_TRUE(scroll_result
.did_scroll
);
4408 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4409 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4410 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4412 // Overscroll events are reflected immediately.
4413 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4414 EXPECT_TRUE(scroll_result
.did_scroll
);
4415 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4416 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4417 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4418 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4419 host_impl_
->accumulated_root_overscroll());
4421 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4422 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4423 EXPECT_TRUE(scroll_result
.did_scroll
);
4424 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4425 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4426 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4427 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4428 host_impl_
->accumulated_root_overscroll());
4430 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4431 EXPECT_FALSE(scroll_result
.did_scroll
);
4432 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4433 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4434 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4435 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4436 host_impl_
->accumulated_root_overscroll());
4438 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4439 EXPECT_TRUE(scroll_result
.did_scroll
);
4440 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4441 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4442 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4443 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4444 host_impl_
->accumulated_root_overscroll());
4446 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4447 EXPECT_TRUE(scroll_result
.did_scroll
);
4448 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4449 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4450 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4451 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4452 host_impl_
->accumulated_root_overscroll());
4454 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4455 EXPECT_TRUE(scroll_result
.did_scroll
);
4456 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4457 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4458 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4459 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4460 host_impl_
->accumulated_root_overscroll());
4462 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4463 EXPECT_TRUE(scroll_result
.did_scroll
);
4464 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4465 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4466 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4467 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4468 host_impl_
->accumulated_root_overscroll());
4470 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4471 // as no scroll occurs.
4472 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4473 EXPECT_FALSE(scroll_result
.did_scroll
);
4474 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4475 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4476 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4477 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4478 host_impl_
->accumulated_root_overscroll());
4480 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4481 EXPECT_FALSE(scroll_result
.did_scroll
);
4482 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4483 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4484 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4485 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4486 host_impl_
->accumulated_root_overscroll());
4488 // Overscroll resets on valid scroll.
4489 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4490 EXPECT_TRUE(scroll_result
.did_scroll
);
4491 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4492 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4493 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4494 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4495 host_impl_
->accumulated_root_overscroll());
4497 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4498 EXPECT_TRUE(scroll_result
.did_scroll
);
4499 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4500 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4501 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4502 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4503 host_impl_
->accumulated_root_overscroll());
4505 host_impl_
->ScrollEnd();
4509 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4510 // Scroll child layers beyond their maximum scroll range and make sure root
4511 // overscroll does not accumulate.
4512 gfx::Size
surface_size(10, 10);
4513 scoped_ptr
<LayerImpl
> root_clip
=
4514 LayerImpl::Create(host_impl_
->active_tree(), 4);
4515 root_clip
->SetHasRenderSurface(true);
4517 scoped_ptr
<LayerImpl
> root
=
4518 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4520 scoped_ptr
<LayerImpl
> grand_child
=
4521 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4523 scoped_ptr
<LayerImpl
> child
=
4524 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4525 LayerImpl
* grand_child_layer
= grand_child
.get();
4526 child
->AddChild(grand_child
.Pass());
4528 LayerImpl
* child_layer
= child
.get();
4529 root
->AddChild(child
.Pass());
4530 root_clip
->AddChild(root
.Pass());
4531 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4532 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4533 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4534 host_impl_
->active_tree()->DidBecomeActive();
4535 host_impl_
->SetViewportSize(surface_size
);
4538 gfx::Vector2d
scroll_delta(0, -10);
4539 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4540 host_impl_
->ScrollBegin(gfx::Point(),
4541 InputHandler::NON_BUBBLING_GESTURE
));
4542 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4543 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4544 host_impl_
->ScrollEnd();
4546 // The next time we scroll we should only scroll the parent, but overscroll
4547 // should still not reach the root layer.
4548 scroll_delta
= gfx::Vector2d(0, -30);
4549 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4550 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4551 InputHandler::NON_BUBBLING_GESTURE
));
4552 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4553 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4554 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4555 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4556 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4557 host_impl_
->ScrollEnd();
4559 // After scrolling the parent, another scroll on the opposite direction
4560 // should scroll the child.
4561 scroll_delta
= gfx::Vector2d(0, 70);
4562 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4563 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4564 InputHandler::NON_BUBBLING_GESTURE
));
4565 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4566 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4567 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4568 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4569 host_impl_
->ScrollEnd();
4573 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4574 // When we try to scroll a non-scrollable child layer, the scroll delta
4575 // should be applied to one of its ancestors if possible. Overscroll should
4576 // be reflected only when it has bubbled up to the root scrolling layer.
4577 gfx::Size
surface_size(10, 10);
4578 gfx::Size
content_size(20, 20);
4579 scoped_ptr
<LayerImpl
> root_clip
=
4580 LayerImpl::Create(host_impl_
->active_tree(), 3);
4581 root_clip
->SetHasRenderSurface(true);
4583 scoped_ptr
<LayerImpl
> root
=
4584 CreateScrollableLayer(1, content_size
, root_clip
.get());
4585 root
->SetIsContainerForFixedPositionLayers(true);
4586 scoped_ptr
<LayerImpl
> child
=
4587 CreateScrollableLayer(2, content_size
, root_clip
.get());
4589 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4590 root
->AddChild(child
.Pass());
4591 root_clip
->AddChild(root
.Pass());
4593 host_impl_
->SetViewportSize(surface_size
);
4594 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4595 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4597 host_impl_
->active_tree()->DidBecomeActive();
4600 gfx::Vector2d
scroll_delta(0, 8);
4601 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4602 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4603 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4604 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4605 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4606 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4607 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4608 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4609 host_impl_
->ScrollEnd();
4613 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4614 LayerTreeSettings settings
;
4615 CreateHostImpl(settings
, CreateOutputSurface());
4617 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4618 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4619 clip_layer
->SetBounds(gfx::Size(50, 50));
4620 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4621 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4623 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4625 // Even though the layer can't scroll the overscroll still happens.
4626 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4627 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4628 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4629 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4632 TEST_F(LayerTreeHostImplTest
, NoOverscrollOnFractionalDeviceScale
) {
4633 gfx::Size
surface_size(980, 1439);
4634 gfx::Size
content_size(980, 1438);
4635 float device_scale_factor
= 1.5f
;
4636 scoped_ptr
<LayerImpl
> root_clip
=
4637 LayerImpl::Create(host_impl_
->active_tree(), 3);
4638 root_clip
->SetHasRenderSurface(true);
4640 scoped_ptr
<LayerImpl
> root
=
4641 CreateScrollableLayer(1, content_size
, root_clip
.get());
4642 root
->SetIsContainerForFixedPositionLayers(true);
4643 scoped_ptr
<LayerImpl
> child
=
4644 CreateScrollableLayer(2, content_size
, root_clip
.get());
4645 root
->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4646 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.326531f
, 0.326531f
,
4648 host_impl_
->SetPageScaleOnActiveTree(0.326531f
);
4649 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4650 root
->AddChild(child
.Pass());
4651 root_clip
->AddChild(root
.Pass());
4653 host_impl_
->SetViewportSize(surface_size
);
4654 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4655 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4656 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4658 host_impl_
->active_tree()->DidBecomeActive();
4661 // Horizontal & Vertical GlowEffect should not be applied when
4662 // content size is less then view port size. For Example Horizontal &
4663 // vertical GlowEffect should not be applied in about:blank page.
4664 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4665 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4666 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4667 EXPECT_EQ(gfx::Vector2dF().ToString(),
4668 host_impl_
->accumulated_root_overscroll().ToString());
4670 host_impl_
->ScrollEnd();
4674 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4675 gfx::Size
surface_size(100, 100);
4676 gfx::Size
content_size(200, 200);
4677 scoped_ptr
<LayerImpl
> root_clip
=
4678 LayerImpl::Create(host_impl_
->active_tree(), 3);
4679 root_clip
->SetHasRenderSurface(true);
4681 scoped_ptr
<LayerImpl
> root
=
4682 CreateScrollableLayer(1, content_size
, root_clip
.get());
4683 root
->SetIsContainerForFixedPositionLayers(true);
4684 scoped_ptr
<LayerImpl
> child
=
4685 CreateScrollableLayer(2, content_size
, root_clip
.get());
4687 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4688 root
->AddChild(child
.Pass());
4689 root_clip
->AddChild(root
.Pass());
4691 host_impl_
->SetViewportSize(surface_size
);
4692 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4693 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4695 host_impl_
->active_tree()->DidBecomeActive();
4698 // Edge glow effect should be applicable only upon reaching Edges
4699 // of the content. unnecessary glow effect calls shouldn't be
4700 // called while scrolling up without reaching the edge of the content.
4701 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4702 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4703 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4704 EXPECT_EQ(gfx::Vector2dF().ToString(),
4705 host_impl_
->accumulated_root_overscroll().ToString());
4706 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4707 EXPECT_EQ(gfx::Vector2dF().ToString(),
4708 host_impl_
->accumulated_root_overscroll().ToString());
4709 host_impl_
->ScrollEnd();
4710 // unusedrootDelta should be subtracted from applied delta so that
4711 // unwanted glow effect calls are not called.
4712 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4713 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4714 InputHandler::NON_BUBBLING_GESTURE
));
4715 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4716 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4717 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4718 host_impl_
->accumulated_root_overscroll().ToString());
4720 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4721 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4722 host_impl_
->accumulated_root_overscroll().ToString());
4723 host_impl_
->ScrollEnd();
4724 // TestCase to check kEpsilon, which prevents minute values to trigger
4725 // gloweffect without reaching edge.
4726 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4727 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4728 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4729 EXPECT_EQ(gfx::Vector2dF().ToString(),
4730 host_impl_
->accumulated_root_overscroll().ToString());
4731 host_impl_
->ScrollEnd();
4735 class BlendStateCheckLayer
: public LayerImpl
{
4737 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4739 ResourceProvider
* resource_provider
) {
4740 return make_scoped_ptr(
4741 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4744 void AppendQuads(RenderPass
* render_pass
,
4745 AppendQuadsData
* append_quads_data
) override
{
4746 quads_appended_
= true;
4748 gfx::Rect opaque_rect
;
4749 if (contents_opaque())
4750 opaque_rect
= quad_rect_
;
4752 opaque_rect
= opaque_content_rect_
;
4753 gfx::Rect visible_quad_rect
= quad_rect_
;
4755 SharedQuadState
* shared_quad_state
=
4756 render_pass
->CreateAndAppendSharedQuadState();
4757 PopulateSharedQuadState(shared_quad_state
);
4759 TileDrawQuad
* test_blending_draw_quad
=
4760 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
4761 test_blending_draw_quad
->SetNew(shared_quad_state
,
4766 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4770 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
4771 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
4772 EXPECT_EQ(has_render_surface_
, !!render_surface());
4775 void SetExpectation(bool blend
, bool has_render_surface
) {
4777 has_render_surface_
= has_render_surface
;
4778 quads_appended_
= false;
4781 bool quads_appended() const { return quads_appended_
; }
4783 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
4784 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
4785 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
4786 opaque_content_rect_
= rect
;
4790 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
4792 ResourceProvider
* resource_provider
)
4793 : LayerImpl(tree_impl
, id
),
4795 has_render_surface_(false),
4796 quads_appended_(false),
4797 quad_rect_(5, 5, 5, 5),
4798 quad_visible_rect_(5, 5, 5, 5),
4799 resource_id_(resource_provider
->CreateResource(
4802 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
4804 resource_provider
->AllocateForTesting(resource_id_
);
4805 SetBounds(gfx::Size(10, 10));
4806 SetDrawsContent(true);
4810 bool has_render_surface_
;
4811 bool quads_appended_
;
4812 gfx::Rect quad_rect_
;
4813 gfx::Rect opaque_content_rect_
;
4814 gfx::Rect quad_visible_rect_
;
4815 ResourceId resource_id_
;
4818 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
4820 scoped_ptr
<LayerImpl
> root
=
4821 LayerImpl::Create(host_impl_
->active_tree(), 1);
4822 root
->SetBounds(gfx::Size(10, 10));
4823 root
->SetDrawsContent(false);
4824 root
->SetHasRenderSurface(true);
4825 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4827 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4830 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4832 host_impl_
->resource_provider()));
4833 BlendStateCheckLayer
* layer1
=
4834 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
4835 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
4837 LayerTreeHostImpl::FrameData frame
;
4839 // Opaque layer, drawn without blending.
4840 layer1
->SetContentsOpaque(true);
4841 layer1
->SetExpectation(false, false);
4842 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4843 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4844 host_impl_
->DrawLayers(&frame
);
4845 EXPECT_TRUE(layer1
->quads_appended());
4846 host_impl_
->DidDrawAllLayers(frame
);
4848 // Layer with translucent content and painting, so drawn with blending.
4849 layer1
->SetContentsOpaque(false);
4850 layer1
->SetExpectation(true, false);
4851 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4852 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4853 host_impl_
->DrawLayers(&frame
);
4854 EXPECT_TRUE(layer1
->quads_appended());
4855 host_impl_
->DidDrawAllLayers(frame
);
4857 // Layer with translucent opacity, drawn with blending.
4858 layer1
->SetContentsOpaque(true);
4859 layer1
->SetOpacity(0.5f
);
4860 layer1
->SetExpectation(true, false);
4861 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4862 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4863 host_impl_
->DrawLayers(&frame
);
4864 EXPECT_TRUE(layer1
->quads_appended());
4865 host_impl_
->DidDrawAllLayers(frame
);
4867 // Layer with translucent opacity and painting, drawn with blending.
4868 layer1
->SetContentsOpaque(true);
4869 layer1
->SetOpacity(0.5f
);
4870 layer1
->SetExpectation(true, false);
4871 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4872 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4873 host_impl_
->DrawLayers(&frame
);
4874 EXPECT_TRUE(layer1
->quads_appended());
4875 host_impl_
->DidDrawAllLayers(frame
);
4878 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4880 host_impl_
->resource_provider()));
4881 BlendStateCheckLayer
* layer2
=
4882 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
4883 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
4885 // 2 opaque layers, drawn without blending.
4886 layer1
->SetContentsOpaque(true);
4887 layer1
->SetOpacity(1.f
);
4888 layer1
->SetExpectation(false, false);
4889 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4890 layer2
->SetContentsOpaque(true);
4891 layer2
->SetOpacity(1.f
);
4892 layer2
->SetExpectation(false, false);
4893 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4894 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4895 host_impl_
->DrawLayers(&frame
);
4896 EXPECT_TRUE(layer1
->quads_appended());
4897 EXPECT_TRUE(layer2
->quads_appended());
4898 host_impl_
->DidDrawAllLayers(frame
);
4900 // Parent layer with translucent content, drawn with blending.
4901 // Child layer with opaque content, drawn without blending.
4902 layer1
->SetContentsOpaque(false);
4903 layer1
->SetExpectation(true, false);
4904 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4905 layer2
->SetExpectation(false, false);
4906 layer2
->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 EXPECT_TRUE(layer2
->quads_appended());
4911 host_impl_
->DidDrawAllLayers(frame
);
4913 // Parent layer with translucent content but opaque painting, drawn without
4915 // Child layer with opaque content, drawn without blending.
4916 layer1
->SetContentsOpaque(true);
4917 layer1
->SetExpectation(false, false);
4918 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4919 layer2
->SetExpectation(false, false);
4920 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4921 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4922 host_impl_
->DrawLayers(&frame
);
4923 EXPECT_TRUE(layer1
->quads_appended());
4924 EXPECT_TRUE(layer2
->quads_appended());
4925 host_impl_
->DidDrawAllLayers(frame
);
4927 // Parent layer with translucent opacity and opaque content. Since it has a
4928 // drawing child, it's drawn to a render surface which carries the opacity,
4929 // so it's itself drawn without blending.
4930 // Child layer with opaque content, drawn without blending (parent surface
4931 // carries the inherited opacity).
4932 layer1
->SetContentsOpaque(true);
4933 layer1
->SetOpacity(0.5f
);
4934 layer1
->SetHasRenderSurface(true);
4935 layer1
->SetExpectation(false, true);
4936 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4937 layer2
->SetExpectation(false, false);
4938 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4939 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4940 host_impl_
->active_tree()->root_layer());
4941 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4942 host_impl_
->DrawLayers(&frame
);
4943 EXPECT_TRUE(layer1
->quads_appended());
4944 EXPECT_TRUE(layer2
->quads_appended());
4945 host_impl_
->DidDrawAllLayers(frame
);
4946 layer1
->SetHasRenderSurface(false);
4948 // Draw again, but with child non-opaque, to make sure
4949 // layer1 not culled.
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(0.5f
);
4956 layer2
->SetExpectation(true, 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 // A second way of making the child non-opaque.
4965 layer1
->SetContentsOpaque(true);
4966 layer1
->SetOpacity(1.f
);
4967 layer1
->SetExpectation(false, false);
4968 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4969 layer2
->SetContentsOpaque(false);
4970 layer2
->SetOpacity(1.f
);
4971 layer2
->SetExpectation(true, false);
4972 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4973 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4974 host_impl_
->DrawLayers(&frame
);
4975 EXPECT_TRUE(layer1
->quads_appended());
4976 EXPECT_TRUE(layer2
->quads_appended());
4977 host_impl_
->DidDrawAllLayers(frame
);
4979 // And when the layer says its not opaque but is painted opaque, it is not
4981 layer1
->SetContentsOpaque(true);
4982 layer1
->SetOpacity(1.f
);
4983 layer1
->SetExpectation(false, false);
4984 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4985 layer2
->SetContentsOpaque(true);
4986 layer2
->SetOpacity(1.f
);
4987 layer2
->SetExpectation(false, false);
4988 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
4989 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4990 host_impl_
->DrawLayers(&frame
);
4991 EXPECT_TRUE(layer1
->quads_appended());
4992 EXPECT_TRUE(layer2
->quads_appended());
4993 host_impl_
->DidDrawAllLayers(frame
);
4995 // Layer with partially opaque contents, drawn with blending.
4996 layer1
->SetContentsOpaque(false);
4997 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4998 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4999 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5000 layer1
->SetExpectation(true, false);
5001 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5002 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5003 host_impl_
->DrawLayers(&frame
);
5004 EXPECT_TRUE(layer1
->quads_appended());
5005 host_impl_
->DidDrawAllLayers(frame
);
5007 // Layer with partially opaque contents partially culled, drawn with blending.
5008 layer1
->SetContentsOpaque(false);
5009 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5010 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5011 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5012 layer1
->SetExpectation(true, false);
5013 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5014 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5015 host_impl_
->DrawLayers(&frame
);
5016 EXPECT_TRUE(layer1
->quads_appended());
5017 host_impl_
->DidDrawAllLayers(frame
);
5019 // Layer with partially opaque contents culled, drawn with blending.
5020 layer1
->SetContentsOpaque(false);
5021 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5022 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5023 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5024 layer1
->SetExpectation(true, false);
5025 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5026 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5027 host_impl_
->DrawLayers(&frame
);
5028 EXPECT_TRUE(layer1
->quads_appended());
5029 host_impl_
->DidDrawAllLayers(frame
);
5031 // Layer with partially opaque contents and translucent contents culled, drawn
5032 // without blending.
5033 layer1
->SetContentsOpaque(false);
5034 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5035 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5036 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5037 layer1
->SetExpectation(false, false);
5038 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5039 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5040 host_impl_
->DrawLayers(&frame
);
5041 EXPECT_TRUE(layer1
->quads_appended());
5042 host_impl_
->DidDrawAllLayers(frame
);
5045 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
5047 LayerTreeHostImplViewportCoveredTest() :
5048 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
5050 did_activate_pending_tree_(false) {}
5052 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
5054 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5056 return FakeOutputSurface::Create3d();
5059 void SetupActiveTreeLayers() {
5060 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
5061 host_impl_
->active_tree()->SetRootLayer(
5062 LayerImpl::Create(host_impl_
->active_tree(), 1));
5063 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
5064 host_impl_
->active_tree()->root_layer()->AddChild(
5065 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5067 host_impl_
->resource_provider()));
5068 child_
= static_cast<BlendStateCheckLayer
*>(
5069 host_impl_
->active_tree()->root_layer()->children()[0]);
5070 child_
->SetExpectation(false, false);
5071 child_
->SetContentsOpaque(true);
5074 // Expect no gutter rects.
5075 void TestLayerCoversFullViewport() {
5076 gfx::Rect
layer_rect(viewport_size_
);
5077 child_
->SetPosition(layer_rect
.origin());
5078 child_
->SetBounds(layer_rect
.size());
5079 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5080 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5082 LayerTreeHostImpl::FrameData frame
;
5083 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5084 ASSERT_EQ(1u, frame
.render_passes
.size());
5086 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5087 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5088 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5090 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5091 host_impl_
->DidDrawAllLayers(frame
);
5094 // Expect fullscreen gutter rect.
5095 void TestEmptyLayer() {
5096 gfx::Rect
layer_rect(0, 0, 0, 0);
5097 child_
->SetPosition(layer_rect
.origin());
5098 child_
->SetBounds(layer_rect
.size());
5099 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5100 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5102 LayerTreeHostImpl::FrameData frame
;
5103 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5104 ASSERT_EQ(1u, frame
.render_passes
.size());
5106 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5107 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5108 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5110 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5111 host_impl_
->DidDrawAllLayers(frame
);
5114 // Expect four surrounding gutter rects.
5115 void TestLayerInMiddleOfViewport() {
5116 gfx::Rect
layer_rect(500, 500, 200, 200);
5117 child_
->SetPosition(layer_rect
.origin());
5118 child_
->SetBounds(layer_rect
.size());
5119 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5120 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5122 LayerTreeHostImpl::FrameData frame
;
5123 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5124 ASSERT_EQ(1u, frame
.render_passes
.size());
5126 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5127 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
5128 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5130 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5131 host_impl_
->DidDrawAllLayers(frame
);
5134 // Expect no gutter rects.
5135 void TestLayerIsLargerThanViewport() {
5136 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
5137 viewport_size_
.height() + 10);
5138 child_
->SetPosition(layer_rect
.origin());
5139 child_
->SetBounds(layer_rect
.size());
5140 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5141 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5143 LayerTreeHostImpl::FrameData frame
;
5144 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5145 ASSERT_EQ(1u, frame
.render_passes
.size());
5147 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5148 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5149 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5151 host_impl_
->DidDrawAllLayers(frame
);
5154 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
5156 void set_gutter_quad_material(DrawQuad::Material material
) {
5157 gutter_quad_material_
= material
;
5159 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
5160 gutter_texture_size_
= gutter_texture_size
;
5164 size_t CountGutterQuads(const QuadList
& quad_list
) {
5165 size_t num_gutter_quads
= 0;
5166 for (const auto& quad
: quad_list
) {
5167 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
5169 return num_gutter_quads
;
5172 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
5173 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5174 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
5177 // Make sure that the texture coordinates match their expectations.
5178 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
5179 for (const auto& quad
: quad_list
) {
5180 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
5182 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
5183 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
5184 gutter_texture_size_
, host_impl_
->device_scale_factor());
5185 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
5186 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
5187 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
5188 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
5190 texture_quad
->uv_bottom_right
.x(),
5191 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
5193 texture_quad
->uv_bottom_right
.y(),
5194 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
5198 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
5199 return gfx::ToRoundedSize(
5200 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
5203 DrawQuad::Material gutter_quad_material_
;
5204 gfx::Size gutter_texture_size_
;
5205 gfx::Size viewport_size_
;
5206 BlendStateCheckLayer
* child_
;
5207 bool did_activate_pending_tree_
;
5210 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
5211 viewport_size_
= gfx::Size(1000, 1000);
5213 bool always_draw
= false;
5214 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5216 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5217 SetupActiveTreeLayers();
5218 TestLayerCoversFullViewport();
5220 TestLayerInMiddleOfViewport();
5221 TestLayerIsLargerThanViewport();
5224 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
5225 viewport_size_
= gfx::Size(1000, 1000);
5227 bool always_draw
= false;
5228 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5230 host_impl_
->SetDeviceScaleFactor(2.f
);
5231 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5232 SetupActiveTreeLayers();
5233 TestLayerCoversFullViewport();
5235 TestLayerInMiddleOfViewport();
5236 TestLayerIsLargerThanViewport();
5239 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
5240 viewport_size_
= gfx::Size(1000, 1000);
5242 bool always_draw
= true;
5243 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5245 // Pending tree to force active_tree size invalid. Not used otherwise.
5246 host_impl_
->CreatePendingTree();
5247 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5248 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5250 SetupActiveTreeLayers();
5252 TestLayerInMiddleOfViewport();
5253 TestLayerIsLargerThanViewport();
5256 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5257 viewport_size_
= gfx::Size(1000, 1000);
5259 bool always_draw
= true;
5260 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5262 // Set larger viewport and activate it to active tree.
5263 host_impl_
->CreatePendingTree();
5264 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5265 viewport_size_
.height() + 100);
5266 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5267 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5268 host_impl_
->ActivateSyncTree();
5269 EXPECT_TRUE(did_activate_pending_tree_
);
5270 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5272 // Shrink pending tree viewport without activating.
5273 host_impl_
->CreatePendingTree();
5274 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5275 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5277 SetupActiveTreeLayers();
5279 TestLayerInMiddleOfViewport();
5280 TestLayerIsLargerThanViewport();
5283 class FakeDrawableLayerImpl
: public LayerImpl
{
5285 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5286 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5289 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5290 : LayerImpl(tree_impl
, id
) {}
5293 // Only reshape when we know we are going to draw. Otherwise, the reshape
5294 // can leave the window at the wrong size if we never draw and the proper
5295 // viewport size is never set.
5296 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5297 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5298 scoped_ptr
<OutputSurface
> output_surface(
5299 FakeOutputSurface::Create3d(provider
));
5300 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5302 scoped_ptr
<LayerImpl
> root
=
5303 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5304 root
->SetBounds(gfx::Size(10, 10));
5305 root
->SetDrawsContent(true);
5306 root
->SetHasRenderSurface(true);
5307 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5308 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5309 provider
->TestContext3d()->clear_reshape_called();
5311 LayerTreeHostImpl::FrameData frame
;
5312 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5313 host_impl_
->SetDeviceScaleFactor(1.f
);
5314 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5315 host_impl_
->DrawLayers(&frame
);
5316 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5317 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5318 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5319 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5320 host_impl_
->DidDrawAllLayers(frame
);
5321 provider
->TestContext3d()->clear_reshape_called();
5323 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5324 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5325 host_impl_
->DrawLayers(&frame
);
5326 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5327 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5328 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5329 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5330 host_impl_
->DidDrawAllLayers(frame
);
5331 provider
->TestContext3d()->clear_reshape_called();
5333 host_impl_
->SetDeviceScaleFactor(2.f
);
5334 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5335 host_impl_
->DrawLayers(&frame
);
5336 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5337 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5338 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5339 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5340 host_impl_
->DidDrawAllLayers(frame
);
5341 provider
->TestContext3d()->clear_reshape_called();
5344 // Make sure damage tracking propagates all the way to the graphics context,
5345 // where it should request to swap only the sub-buffer that is damaged.
5346 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5347 scoped_refptr
<TestContextProvider
> context_provider(
5348 TestContextProvider::Create());
5349 context_provider
->BindToCurrentThread();
5350 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5352 scoped_ptr
<FakeOutputSurface
> output_surface(
5353 FakeOutputSurface::Create3d(context_provider
));
5354 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5356 // This test creates its own LayerTreeHostImpl, so
5357 // that we can force partial swap enabled.
5358 LayerTreeSettings settings
;
5359 settings
.renderer_settings
.partial_swap_enabled
= true;
5360 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5361 LayerTreeHostImpl::Create(
5362 settings
, this, &proxy_
, &stats_instrumentation_
,
5363 &shared_bitmap_manager_
, NULL
, &task_graph_runner_
, 0);
5364 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5365 layer_tree_host_impl
->WillBeginImplFrame(
5366 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5367 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5369 scoped_ptr
<LayerImpl
> root
=
5370 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5371 root
->SetHasRenderSurface(true);
5372 scoped_ptr
<LayerImpl
> child
=
5373 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5374 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5375 child
->SetBounds(gfx::Size(14, 15));
5376 child
->SetDrawsContent(true);
5377 root
->SetBounds(gfx::Size(500, 500));
5378 root
->SetDrawsContent(true);
5379 root
->AddChild(child
.Pass());
5380 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5382 LayerTreeHostImpl::FrameData frame
;
5384 // First frame, the entire screen should get swapped.
5385 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5386 layer_tree_host_impl
->DrawLayers(&frame
);
5387 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5388 layer_tree_host_impl
->SwapBuffers(frame
);
5389 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5390 EXPECT_EQ(expected_swap_rect
.ToString(),
5391 fake_output_surface
->last_swap_rect().ToString());
5393 // Second frame, only the damaged area should get swapped. Damage should be
5394 // the union of old and new child rects.
5395 // expected damage rect: gfx::Rect(26, 28);
5396 // expected swap rect: vertically flipped, with origin at bottom left corner.
5397 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5399 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5400 layer_tree_host_impl
->DrawLayers(&frame
);
5401 host_impl_
->DidDrawAllLayers(frame
);
5402 layer_tree_host_impl
->SwapBuffers(frame
);
5404 // Make sure that partial swap is constrained to the viewport dimensions
5405 // expected damage rect: gfx::Rect(500, 500);
5406 // expected swap rect: flipped damage rect, but also clamped to viewport
5407 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5408 EXPECT_EQ(expected_swap_rect
.ToString(),
5409 fake_output_surface
->last_swap_rect().ToString());
5411 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5412 // This will damage everything.
5413 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5415 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5416 layer_tree_host_impl
->DrawLayers(&frame
);
5417 host_impl_
->DidDrawAllLayers(frame
);
5418 layer_tree_host_impl
->SwapBuffers(frame
);
5420 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5421 EXPECT_EQ(expected_swap_rect
.ToString(),
5422 fake_output_surface
->last_swap_rect().ToString());
5425 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5426 scoped_ptr
<LayerImpl
> root
=
5427 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5428 scoped_ptr
<LayerImpl
> child
=
5429 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5430 child
->SetBounds(gfx::Size(10, 10));
5431 child
->SetDrawsContent(true);
5432 root
->SetBounds(gfx::Size(10, 10));
5433 root
->SetDrawsContent(true);
5434 root
->SetHasRenderSurface(true);
5435 root
->AddChild(child
.Pass());
5437 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5439 LayerTreeHostImpl::FrameData frame
;
5441 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5442 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5443 EXPECT_EQ(1u, frame
.render_passes
.size());
5444 host_impl_
->DidDrawAllLayers(frame
);
5447 class FakeLayerWithQuads
: public LayerImpl
{
5449 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5450 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5453 void AppendQuads(RenderPass
* render_pass
,
5454 AppendQuadsData
* append_quads_data
) override
{
5455 SharedQuadState
* shared_quad_state
=
5456 render_pass
->CreateAndAppendSharedQuadState();
5457 PopulateSharedQuadState(shared_quad_state
);
5459 SkColor gray
= SkColorSetRGB(100, 100, 100);
5460 gfx::Rect
quad_rect(bounds());
5461 gfx::Rect
visible_quad_rect(quad_rect
);
5462 SolidColorDrawQuad
* my_quad
=
5463 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5465 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5469 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5470 : LayerImpl(tree_impl
, id
) {}
5473 class MockContext
: public TestWebGraphicsContext3D
{
5475 MOCK_METHOD1(useProgram
, void(GLuint program
));
5476 MOCK_METHOD5(uniform4f
, void(GLint location
,
5481 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5483 GLboolean transpose
,
5484 const GLfloat
* value
));
5485 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5489 MOCK_METHOD1(enable
, void(GLenum cap
));
5490 MOCK_METHOD1(disable
, void(GLenum cap
));
5491 MOCK_METHOD4(scissor
, void(GLint x
,
5497 class MockContextHarness
{
5499 MockContext
* context_
;
5502 explicit MockContextHarness(MockContext
* context
)
5503 : context_(context
) {
5504 context_
->set_have_post_sub_buffer(true);
5506 // Catch "uninteresting" calls
5507 EXPECT_CALL(*context_
, useProgram(_
))
5510 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5513 // These are not asserted
5514 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5515 .WillRepeatedly(Return());
5517 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5518 .WillRepeatedly(Return());
5520 // Any un-sanctioned calls to enable() are OK
5521 EXPECT_CALL(*context_
, enable(_
))
5522 .WillRepeatedly(Return());
5524 // Any un-sanctioned calls to disable() are OK
5525 EXPECT_CALL(*context_
, disable(_
))
5526 .WillRepeatedly(Return());
5529 void MustDrawSolidQuad() {
5530 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5532 .RetiresOnSaturation();
5534 EXPECT_CALL(*context_
, useProgram(_
))
5536 .RetiresOnSaturation();
5539 void MustSetScissor(int x
, int y
, int width
, int height
) {
5540 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5541 .WillRepeatedly(Return());
5543 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5545 .WillRepeatedly(Return());
5548 void MustSetNoScissor() {
5549 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5550 .WillRepeatedly(Return());
5552 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5555 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5560 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5561 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5562 MockContext
* mock_context
= mock_context_owned
.get();
5563 MockContextHarness
harness(mock_context
);
5566 LayerTreeSettings settings
= DefaultSettings();
5567 settings
.renderer_settings
.partial_swap_enabled
= false;
5568 CreateHostImpl(settings
,
5569 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5570 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5572 // Without partial swap, and no clipping, no scissor is set.
5573 harness
.MustDrawSolidQuad();
5574 harness
.MustSetNoScissor();
5576 LayerTreeHostImpl::FrameData frame
;
5577 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5578 host_impl_
->DrawLayers(&frame
);
5579 host_impl_
->DidDrawAllLayers(frame
);
5581 Mock::VerifyAndClearExpectations(&mock_context
);
5583 // Without partial swap, but a layer does clip its subtree, one scissor is
5585 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5586 harness
.MustDrawSolidQuad();
5587 harness
.MustSetScissor(0, 0, 10, 10);
5589 LayerTreeHostImpl::FrameData frame
;
5590 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5591 host_impl_
->DrawLayers(&frame
);
5592 host_impl_
->DidDrawAllLayers(frame
);
5594 Mock::VerifyAndClearExpectations(&mock_context
);
5597 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5598 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5599 MockContext
* mock_context
= context_owned
.get();
5600 MockContextHarness
harness(mock_context
);
5602 LayerTreeSettings settings
= DefaultSettings();
5603 settings
.renderer_settings
.partial_swap_enabled
= true;
5604 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5605 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5607 // The first frame is not a partially-swapped one. No scissor should be set.
5608 harness
.MustSetNoScissor();
5609 harness
.MustDrawSolidQuad();
5611 LayerTreeHostImpl::FrameData frame
;
5612 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5613 host_impl_
->DrawLayers(&frame
);
5614 host_impl_
->DidDrawAllLayers(frame
);
5616 Mock::VerifyAndClearExpectations(&mock_context
);
5618 // Damage a portion of the frame.
5619 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5620 gfx::Rect(0, 0, 2, 3));
5622 // The second frame will be partially-swapped (the y coordinates are flipped).
5623 harness
.MustSetScissor(0, 7, 2, 3);
5624 harness
.MustDrawSolidQuad();
5626 LayerTreeHostImpl::FrameData frame
;
5627 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5628 host_impl_
->DrawLayers(&frame
);
5629 host_impl_
->DidDrawAllLayers(frame
);
5631 Mock::VerifyAndClearExpectations(&mock_context
);
5634 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5636 LayerTreeHostImplClient
* client
,
5638 SharedBitmapManager
* manager
,
5639 TaskGraphRunner
* task_graph_runner
,
5640 RenderingStatsInstrumentation
* stats_instrumentation
) {
5641 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5642 scoped_ptr
<OutputSurface
> output_surface(
5643 FakeOutputSurface::Create3d(provider
));
5644 provider
->BindToCurrentThread();
5645 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5647 LayerTreeSettings settings
;
5648 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5649 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5650 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
,
5651 manager
, nullptr, task_graph_runner
, 0);
5652 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5653 my_host_impl
->WillBeginImplFrame(
5654 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5655 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5658 Layers are created as follows:
5660 +--------------------+
5664 | | +-------------------+
5666 | | +-------------------+
5671 +--------------------+
5673 Layers 1, 2 have render surfaces
5675 scoped_ptr
<LayerImpl
> root
=
5676 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5677 scoped_ptr
<LayerImpl
> child
=
5678 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5679 scoped_ptr
<LayerImpl
> grand_child
=
5680 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5682 gfx::Rect
root_rect(0, 0, 100, 100);
5683 gfx::Rect
child_rect(10, 10, 50, 50);
5684 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5686 root
->SetHasRenderSurface(true);
5687 root
->SetPosition(root_rect
.origin());
5688 root
->SetBounds(root_rect
.size());
5689 root
->draw_properties().visible_layer_rect
= root_rect
;
5690 root
->SetDrawsContent(false);
5691 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5693 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5694 child
->SetOpacity(0.5f
);
5695 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5696 child
->draw_properties().visible_layer_rect
= child_rect
;
5697 child
->SetDrawsContent(false);
5698 child
->SetHasRenderSurface(true);
5700 grand_child
->SetPosition(grand_child_rect
.origin());
5701 grand_child
->SetBounds(grand_child_rect
.size());
5702 grand_child
->draw_properties().visible_layer_rect
= grand_child_rect
;
5703 grand_child
->SetDrawsContent(true);
5705 child
->AddChild(grand_child
.Pass());
5706 root
->AddChild(child
.Pass());
5708 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5709 return my_host_impl
.Pass();
5712 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5713 TestSharedBitmapManager shared_bitmap_manager
;
5714 TestTaskGraphRunner task_graph_runner
;
5715 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5716 SetupLayersForOpacity(true, this, &proxy_
, &shared_bitmap_manager
,
5717 &task_graph_runner
, &stats_instrumentation_
);
5719 LayerTreeHostImpl::FrameData frame
;
5720 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5722 // Verify all quads have been computed
5723 ASSERT_EQ(2U, frame
.render_passes
.size());
5724 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5725 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5726 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5727 frame
.render_passes
[0]->quad_list
.front()->material
);
5728 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5729 frame
.render_passes
[1]->quad_list
.front()->material
);
5731 my_host_impl
->DrawLayers(&frame
);
5732 my_host_impl
->DidDrawAllLayers(frame
);
5736 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5737 TestSharedBitmapManager shared_bitmap_manager
;
5738 TestTaskGraphRunner task_graph_runner
;
5739 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5740 SetupLayersForOpacity(false, this, &proxy_
, &shared_bitmap_manager
,
5741 &task_graph_runner
, &stats_instrumentation_
);
5743 LayerTreeHostImpl::FrameData frame
;
5744 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5746 // Verify all quads have been computed
5747 ASSERT_EQ(2U, frame
.render_passes
.size());
5748 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5749 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5750 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5751 frame
.render_passes
[0]->quad_list
.front()->material
);
5752 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5753 frame
.render_passes
[1]->quad_list
.front()->material
);
5755 my_host_impl
->DrawLayers(&frame
);
5756 my_host_impl
->DidDrawAllLayers(frame
);
5760 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
5761 scoped_ptr
<TestWebGraphicsContext3D
> context
=
5762 TestWebGraphicsContext3D::Create();
5763 TestWebGraphicsContext3D
* context3d
= context
.get();
5764 scoped_ptr
<OutputSurface
> output_surface(
5765 FakeOutputSurface::Create3d(context
.Pass()));
5766 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5768 scoped_ptr
<LayerImpl
> root_layer
=
5769 LayerImpl::Create(host_impl_
->active_tree(), 1);
5770 root_layer
->SetBounds(gfx::Size(10, 10));
5771 root_layer
->SetHasRenderSurface(true);
5773 scoped_refptr
<VideoFrame
> softwareFrame
=
5774 media::VideoFrame::CreateColorFrame(
5775 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5776 FakeVideoFrameProvider provider
;
5777 provider
.set_frame(softwareFrame
);
5778 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5779 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
5780 video_layer
->SetBounds(gfx::Size(10, 10));
5781 video_layer
->SetDrawsContent(true);
5782 root_layer
->AddChild(video_layer
.Pass());
5784 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
5785 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
5786 io_surface_layer
->SetBounds(gfx::Size(10, 10));
5787 io_surface_layer
->SetDrawsContent(true);
5788 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5789 root_layer
->AddChild(io_surface_layer
.Pass());
5791 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
5793 EXPECT_EQ(0u, context3d
->NumTextures());
5795 LayerTreeHostImpl::FrameData frame
;
5796 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5797 host_impl_
->DrawLayers(&frame
);
5798 host_impl_
->DidDrawAllLayers(frame
);
5799 host_impl_
->SwapBuffers(frame
);
5801 EXPECT_GT(context3d
->NumTextures(), 0u);
5803 // Kill the layer tree.
5804 host_impl_
->active_tree()->SetRootLayer(
5805 LayerImpl::Create(host_impl_
->active_tree(), 100));
5806 // There should be no textures left in use after.
5807 EXPECT_EQ(0u, context3d
->NumTextures());
5810 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
5812 MOCK_METHOD1(useProgram
, void(GLuint program
));
5813 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5819 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
5820 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
5821 new MockDrawQuadsToFillScreenContext
);
5822 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
5825 LayerTreeSettings settings
= DefaultSettings();
5826 settings
.renderer_settings
.partial_swap_enabled
= false;
5827 CreateHostImpl(settings
,
5828 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5829 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
5830 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
5832 // Verify one quad is drawn when transparent background set is not set.
5833 host_impl_
->active_tree()->set_has_transparent_background(false);
5834 EXPECT_CALL(*mock_context
, useProgram(_
))
5836 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
5838 LayerTreeHostImpl::FrameData frame
;
5839 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5840 host_impl_
->DrawLayers(&frame
);
5841 host_impl_
->DidDrawAllLayers(frame
);
5842 Mock::VerifyAndClearExpectations(&mock_context
);
5844 // Verify no quads are drawn when transparent background is set.
5845 host_impl_
->active_tree()->set_has_transparent_background(true);
5846 host_impl_
->SetFullRootLayerDamage();
5847 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5848 host_impl_
->DrawLayers(&frame
);
5849 host_impl_
->DidDrawAllLayers(frame
);
5850 Mock::VerifyAndClearExpectations(&mock_context
);
5853 class LayerTreeHostImplTestWithDelegatingRenderer
5854 : public LayerTreeHostImplTest
{
5856 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
5857 return FakeOutputSurface::CreateDelegating3d();
5860 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
5861 bool expect_to_draw
= !expected_damage
.IsEmpty();
5863 LayerTreeHostImpl::FrameData frame
;
5864 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5866 if (!expect_to_draw
) {
5867 // With no damage, we don't draw, and no quads are created.
5868 ASSERT_EQ(0u, frame
.render_passes
.size());
5870 ASSERT_EQ(1u, frame
.render_passes
.size());
5872 // Verify the damage rect for the root render pass.
5873 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
5874 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
5876 // Verify the root and child layers' quads are generated and not being
5878 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
5880 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
5881 gfx::RectF
expected_child_visible_rect(child
->bounds());
5882 EXPECT_EQ(expected_child_visible_rect
,
5883 root_render_pass
->quad_list
.front()->visible_rect
);
5885 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5886 gfx::RectF
expected_root_visible_rect(root
->bounds());
5887 EXPECT_EQ(expected_root_visible_rect
,
5888 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
5891 host_impl_
->DrawLayers(&frame
);
5892 host_impl_
->DidDrawAllLayers(frame
);
5893 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
5897 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
5898 scoped_ptr
<SolidColorLayerImpl
> root
=
5899 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5900 root
->SetPosition(gfx::PointF());
5901 root
->SetBounds(gfx::Size(10, 10));
5902 root
->SetDrawsContent(true);
5903 root
->SetHasRenderSurface(true);
5905 // Child layer is in the bottom right corner.
5906 scoped_ptr
<SolidColorLayerImpl
> child
=
5907 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
5908 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
5909 child
->SetBounds(gfx::Size(1, 1));
5910 child
->SetDrawsContent(true);
5911 root
->AddChild(child
.Pass());
5913 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5915 // Draw a frame. In the first frame, the entire viewport should be damaged.
5916 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
5917 DrawFrameAndTestDamage(full_frame_damage
);
5919 // The second frame has damage that doesn't touch the child layer. Its quads
5920 // should still be generated.
5921 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
5922 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
5923 DrawFrameAndTestDamage(small_damage
);
5925 // The third frame should have no damage, so no quads should be generated.
5926 gfx::Rect no_damage
;
5927 DrawFrameAndTestDamage(no_damage
);
5930 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5931 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5932 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
5933 LayerTreeSettings settings
;
5934 CreateHostImpl(settings
, CreateOutputSurface());
5935 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
5938 class FakeMaskLayerImpl
: public LayerImpl
{
5940 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
5942 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
5945 void GetContentsResourceId(ResourceId
* resource_id
,
5946 gfx::Size
* resource_size
) const override
{
5951 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5952 : LayerImpl(tree_impl
, id
) {}
5955 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
5957 using GLRenderer::ShouldAntialiasQuad
;
5960 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
5961 // Due to precision issues (especially on Android), sometimes far
5962 // away quads can end up thinking they need AA.
5963 float device_scale_factor
= 4.f
/ 3.f
;
5964 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5965 gfx::Size
root_size(2000, 1000);
5966 gfx::Size device_viewport_size
=
5967 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5968 host_impl_
->SetViewportSize(device_viewport_size
);
5970 host_impl_
->CreatePendingTree();
5971 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
5974 scoped_ptr
<LayerImpl
> scoped_root
=
5975 LayerImpl::Create(host_impl_
->pending_tree(), 1);
5976 LayerImpl
* root
= scoped_root
.get();
5977 root
->SetHasRenderSurface(true);
5979 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
5981 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
5982 LayerImpl::Create(host_impl_
->pending_tree(), 2);
5983 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
5984 root
->AddChild(scoped_scrolling_layer
.Pass());
5986 gfx::Size
content_layer_bounds(100000, 100);
5987 gfx::Size
pile_tile_size(3000, 3000);
5988 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
5989 pile_tile_size
, content_layer_bounds
));
5991 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
5992 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
5994 LayerImpl
* content_layer
= scoped_content_layer
.get();
5995 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
5996 content_layer
->SetBounds(content_layer_bounds
);
5997 content_layer
->SetDrawsContent(true);
5999 root
->SetBounds(root_size
);
6001 gfx::ScrollOffset
scroll_offset(100000, 0);
6002 scrolling_layer
->SetScrollClipLayer(root
->id());
6003 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
6005 host_impl_
->ActivateSyncTree();
6007 bool update_lcd_text
= false;
6008 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
6009 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
6011 LayerTreeHostImpl::FrameData frame
;
6012 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6014 ASSERT_EQ(1u, frame
.render_passes
.size());
6015 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
6016 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
6018 bool clipped
= false, force_aa
= false;
6019 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
6020 quad
->shared_quad_state
->quad_to_target_transform
,
6021 gfx::QuadF(quad
->shared_quad_state
->visible_quad_layer_rect
), &clipped
);
6022 EXPECT_FALSE(clipped
);
6024 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6025 device_layer_quad
, clipped
, force_aa
);
6026 EXPECT_FALSE(antialiased
);
6028 host_impl_
->DrawLayers(&frame
);
6029 host_impl_
->DidDrawAllLayers(frame
);
6033 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
6035 CompositorFrameMetadataTest()
6036 : swap_buffers_complete_(0) {}
6038 void DidSwapBuffersCompleteOnImplThread() override
{
6039 swap_buffers_complete_
++;
6042 int swap_buffers_complete_
;
6045 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
6046 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
6048 LayerTreeHostImpl::FrameData frame
;
6049 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6050 host_impl_
->DrawLayers(&frame
);
6051 host_impl_
->DidDrawAllLayers(frame
);
6053 CompositorFrameAck ack
;
6054 host_impl_
->ReclaimResources(&ack
);
6055 host_impl_
->DidSwapBuffersComplete();
6056 EXPECT_EQ(swap_buffers_complete_
, 1);
6059 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
6061 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6063 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
6065 return SoftwareOutputDevice::BeginPaint(damage_rect
);
6067 void EndPaint(SoftwareFrameData
* frame_data
) override
{
6069 SoftwareOutputDevice::EndPaint(frame_data
);
6072 int frames_began_
, frames_ended_
;
6075 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
6076 // No main thread evictions in resourceless software mode.
6077 set_reduce_memory_result(false);
6078 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
6079 EXPECT_TRUE(CreateHostImpl(
6081 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
6082 host_impl_
->SetViewportSize(gfx::Size(50, 50));
6084 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6086 const gfx::Transform external_transform
;
6087 const gfx::Rect external_viewport
;
6088 const gfx::Rect external_clip
;
6089 const bool resourceless_software_draw
= true;
6090 host_impl_
->SetExternalDrawConstraints(external_transform
,
6095 resourceless_software_draw
);
6097 EXPECT_EQ(0, software_device
->frames_began_
);
6098 EXPECT_EQ(0, software_device
->frames_ended_
);
6102 EXPECT_EQ(1, software_device
->frames_began_
);
6103 EXPECT_EQ(1, software_device
->frames_ended_
);
6105 // Call another API method that is likely to hit nullptr in this mode.
6106 scoped_refptr
<base::trace_event::TracedValue
> state
=
6107 make_scoped_refptr(new base::trace_event::TracedValue());
6108 host_impl_
->ActivationStateAsValueInto(state
.get());
6111 TEST_F(LayerTreeHostImplTest
,
6112 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
6113 set_reduce_memory_result(false);
6114 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6115 FakeOutputSurface::CreateSoftware(
6116 make_scoped_ptr(new CountingSoftwareDevice
))));
6118 const gfx::Transform external_transform
;
6119 const gfx::Rect external_viewport
;
6120 const gfx::Rect external_clip
;
6121 const bool resourceless_software_draw
= true;
6122 host_impl_
->SetExternalDrawConstraints(external_transform
,
6127 resourceless_software_draw
);
6129 // SolidColorLayerImpl will be drawn.
6130 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
6131 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6133 // VideoLayerImpl will not be drawn.
6134 FakeVideoFrameProvider provider
;
6135 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6136 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
6137 video_layer
->SetBounds(gfx::Size(10, 10));
6138 video_layer
->SetDrawsContent(true);
6139 root_layer
->AddChild(video_layer
.Pass());
6140 SetupRootLayerImpl(root_layer
.Pass());
6142 LayerTreeHostImpl::FrameData frame
;
6143 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6144 host_impl_
->DrawLayers(&frame
);
6145 host_impl_
->DidDrawAllLayers(frame
);
6147 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
6148 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
6151 // Checks that we have a non-0 default allocation if we pass a context that
6152 // doesn't support memory management extensions.
6153 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
6154 LayerTreeSettings settings
;
6155 host_impl_
= LayerTreeHostImpl::Create(
6156 settings
, this, &proxy_
, &stats_instrumentation_
, &shared_bitmap_manager_
,
6157 &gpu_memory_buffer_manager_
, &task_graph_runner_
, 0);
6159 scoped_ptr
<OutputSurface
> output_surface(
6160 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6161 host_impl_
->InitializeRenderer(output_surface
.Pass());
6162 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
6165 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6166 ASSERT_TRUE(host_impl_
->active_tree());
6168 // RequiresHighResToDraw is set when new output surface is used.
6169 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6171 host_impl_
->ResetRequiresHighResToDraw();
6173 host_impl_
->SetVisible(false);
6174 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6175 host_impl_
->SetVisible(true);
6176 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6177 host_impl_
->SetVisible(false);
6178 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6180 host_impl_
->ResetRequiresHighResToDraw();
6182 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6183 host_impl_
->SetVisible(true);
6184 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6187 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6188 ASSERT_TRUE(host_impl_
->active_tree());
6189 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6191 // RequiresHighResToDraw is set when new output surface is used.
6192 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6194 host_impl_
->ResetRequiresHighResToDraw();
6196 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6197 host_impl_
->SetHasGpuRasterizationTrigger(false);
6198 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6199 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6200 host_impl_
->SetHasGpuRasterizationTrigger(true);
6201 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6202 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6203 host_impl_
->SetHasGpuRasterizationTrigger(false);
6204 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6205 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6207 host_impl_
->ResetRequiresHighResToDraw();
6209 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6210 host_impl_
->SetHasGpuRasterizationTrigger(true);
6211 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6212 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6215 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6217 void SetUp() override
{
6219 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_
,
6220 &shared_bitmap_manager_
, &task_graph_runner_
);
6221 host_impl_
.reset(fake_host_impl_
);
6222 host_impl_
->InitializeRenderer(CreateOutputSurface());
6223 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6226 FakeLayerTreeHostImpl
* fake_host_impl_
;
6229 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6230 fake_host_impl_
->DidModifyTilePriorities();
6231 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6232 fake_host_impl_
->SetVisible(false);
6233 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6236 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6237 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6238 TestWebGraphicsContext3D::Create();
6239 TestWebGraphicsContext3D
* context3d
= context
.get();
6240 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6241 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6243 EXPECT_EQ(0u, context3d
->NumTextures());
6245 UIResourceId ui_resource_id
= 1;
6246 bool is_opaque
= false;
6247 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6248 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6249 EXPECT_EQ(1u, context3d
->NumTextures());
6250 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6253 // Multiple requests with the same id is allowed. The previous texture is
6255 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6256 EXPECT_EQ(1u, context3d
->NumTextures());
6257 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6259 EXPECT_NE(id1
, id2
);
6261 // Deleting invalid UIResourceId is allowed and does not change state.
6262 host_impl_
->DeleteUIResource(-1);
6263 EXPECT_EQ(1u, context3d
->NumTextures());
6265 // Should return zero for invalid UIResourceId. Number of textures should
6267 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6268 EXPECT_EQ(1u, context3d
->NumTextures());
6270 host_impl_
->DeleteUIResource(ui_resource_id
);
6271 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6272 EXPECT_EQ(0u, context3d
->NumTextures());
6274 // Should not change state for multiple deletion on one UIResourceId
6275 host_impl_
->DeleteUIResource(ui_resource_id
);
6276 EXPECT_EQ(0u, context3d
->NumTextures());
6279 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6280 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6281 TestWebGraphicsContext3D::Create();
6282 TestWebGraphicsContext3D
* context3d
= context
.get();
6283 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6285 EXPECT_EQ(0u, context3d
->NumTextures());
6287 gfx::Size
size(4, 4);
6288 // SkImageInfo has no support for ETC1. The |info| below contains the right
6289 // total pixel size for the bitmap but not the right height and width. The
6290 // correct width/height are passed directly to UIResourceBitmap.
6292 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6293 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6294 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6295 pixel_ref
->setImmutable();
6296 UIResourceBitmap
bitmap(pixel_ref
, size
);
6297 UIResourceId ui_resource_id
= 1;
6298 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6299 EXPECT_EQ(1u, context3d
->NumTextures());
6300 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6304 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6307 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6308 scoped_refptr
<TestContextProvider
> context_provider
=
6309 TestContextProvider::Create();
6311 CreateHostImpl(DefaultSettings(),
6312 FakeOutputSurface::Create3d(context_provider
));
6314 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6316 ScopedPtrVector
<CopyOutputRequest
> requests
;
6317 requests
.push_back(CopyOutputRequest::CreateRequest(
6318 base::Bind(&ShutdownReleasesContext_Callback
)));
6320 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6322 LayerTreeHostImpl::FrameData frame
;
6323 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6324 host_impl_
->DrawLayers(&frame
);
6325 host_impl_
->DidDrawAllLayers(frame
);
6327 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6328 // texture in a texture mailbox.
6329 EXPECT_FALSE(context_provider
->HasOneRef());
6330 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6332 host_impl_
= nullptr;
6334 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6335 // released, and the texture deleted.
6336 EXPECT_TRUE(context_provider
->HasOneRef());
6337 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6340 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6341 // When flinging via touch, only the child should scroll (we should not
6343 gfx::Size
surface_size(10, 10);
6344 gfx::Size
content_size(20, 20);
6345 scoped_ptr
<LayerImpl
> root_clip
=
6346 LayerImpl::Create(host_impl_
->active_tree(), 3);
6347 root_clip
->SetHasRenderSurface(true);
6349 scoped_ptr
<LayerImpl
> root
=
6350 CreateScrollableLayer(1, content_size
, root_clip
.get());
6351 root
->SetIsContainerForFixedPositionLayers(true);
6352 scoped_ptr
<LayerImpl
> child
=
6353 CreateScrollableLayer(2, content_size
, root_clip
.get());
6355 root
->AddChild(child
.Pass());
6356 int root_id
= root
->id();
6357 root_clip
->AddChild(root
.Pass());
6359 host_impl_
->SetViewportSize(surface_size
);
6360 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6361 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6363 host_impl_
->active_tree()->DidBecomeActive();
6366 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6367 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6369 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6371 gfx::Vector2d
scroll_delta(0, 100);
6372 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6373 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6375 host_impl_
->ScrollEnd();
6377 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6378 host_impl_
->ProcessScrollDeltas();
6380 // Only the child should have scrolled.
6381 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6382 ExpectNone(*scroll_info
.get(), root_id
);
6386 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6387 // Scroll a child layer beyond its maximum scroll range and make sure the
6388 // the scroll doesn't bubble up to the parent layer.
6389 gfx::Size
surface_size(10, 10);
6390 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6391 root
->SetHasRenderSurface(true);
6392 scoped_ptr
<LayerImpl
> root_scrolling
=
6393 CreateScrollableLayer(2, surface_size
, root
.get());
6395 scoped_ptr
<LayerImpl
> grand_child
=
6396 CreateScrollableLayer(4, surface_size
, root
.get());
6397 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6399 scoped_ptr
<LayerImpl
> child
=
6400 CreateScrollableLayer(3, surface_size
, root
.get());
6401 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6402 child
->AddChild(grand_child
.Pass());
6404 root_scrolling
->AddChild(child
.Pass());
6405 root
->AddChild(root_scrolling
.Pass());
6406 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6407 host_impl_
->active_tree()->DidBecomeActive();
6408 host_impl_
->SetViewportSize(surface_size
);
6411 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6413 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6414 LayerImpl
* grand_child
= child
->children()[0];
6416 gfx::Vector2d
scroll_delta(0, -2);
6417 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6418 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6419 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6421 // The grand child should have scrolled up to its limit.
6422 scroll_info
= host_impl_
->ProcessScrollDeltas();
6423 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6425 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6426 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6428 // The child should have received the bubbled delta, but the locked
6429 // scrolling layer should remain set as the grand child.
6430 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6431 scroll_info
= host_impl_
->ProcessScrollDeltas();
6432 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6434 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6435 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(), scroll_delta
));
6436 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6438 // The first |ScrollBy| after the fling should re-lock the scrolling
6439 // layer to the first layer that scrolled, which is the child.
6440 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6441 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6442 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6444 // The child should have scrolled up to its limit.
6445 scroll_info
= host_impl_
->ProcessScrollDeltas();
6446 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6448 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6449 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(),
6450 scroll_delta
+ scroll_delta
));
6452 // As the locked layer is at it's limit, no further scrolling can occur.
6453 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6454 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6455 host_impl_
->ScrollEnd();
6459 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6460 // When flinging via wheel, the root should eventually scroll (we should
6462 gfx::Size
surface_size(10, 10);
6463 gfx::Size
content_size(20, 20);
6464 scoped_ptr
<LayerImpl
> root_clip
=
6465 LayerImpl::Create(host_impl_
->active_tree(), 3);
6466 root_clip
->SetHasRenderSurface(true);
6467 scoped_ptr
<LayerImpl
> root_scroll
=
6468 CreateScrollableLayer(1, content_size
, root_clip
.get());
6469 int root_scroll_id
= root_scroll
->id();
6470 scoped_ptr
<LayerImpl
> child
=
6471 CreateScrollableLayer(2, content_size
, root_clip
.get());
6473 root_scroll
->AddChild(child
.Pass());
6474 root_clip
->AddChild(root_scroll
.Pass());
6476 host_impl_
->SetViewportSize(surface_size
);
6477 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6478 host_impl_
->active_tree()->DidBecomeActive();
6481 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6482 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6484 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6486 gfx::Vector2d
scroll_delta(0, 100);
6487 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6488 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6490 host_impl_
->ScrollEnd();
6492 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6493 host_impl_
->ProcessScrollDeltas();
6495 // The root should have scrolled.
6496 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6497 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll_id
,
6498 gfx::Vector2d(0, 10)));
6502 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6503 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6504 // we should return SCROLL_UNKNOWN.
6505 gfx::Size
content_size(100, 100);
6506 SetupScrollAndContentsLayers(content_size
);
6508 int scroll_layer_id
= 2;
6509 LayerImpl
* scroll_layer
=
6510 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6511 scroll_layer
->SetDrawsContent(true);
6513 int page_scale_layer_id
= 5;
6514 LayerImpl
* page_scale_layer
=
6515 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6517 int occluder_layer_id
= 6;
6518 scoped_ptr
<LayerImpl
> occluder_layer
=
6519 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6520 occluder_layer
->SetDrawsContent(true);
6521 occluder_layer
->SetBounds(content_size
);
6522 occluder_layer
->SetPosition(gfx::PointF());
6524 // The parent of the occluder is *above* the scroller.
6525 page_scale_layer
->AddChild(occluder_layer
.Pass());
6529 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6530 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6533 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6534 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6535 // is not the first scroller we encounter when walking up from the layer, we
6536 // should also return SCROLL_UNKNOWN.
6537 gfx::Size
content_size(100, 100);
6538 SetupScrollAndContentsLayers(content_size
);
6540 int scroll_layer_id
= 2;
6541 LayerImpl
* scroll_layer
=
6542 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6543 scroll_layer
->SetDrawsContent(true);
6545 int occluder_layer_id
= 6;
6546 scoped_ptr
<LayerImpl
> occluder_layer
=
6547 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6548 occluder_layer
->SetDrawsContent(true);
6549 occluder_layer
->SetBounds(content_size
);
6550 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6552 int child_scroll_clip_layer_id
= 7;
6553 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6554 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6556 int child_scroll_layer_id
= 8;
6557 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6558 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6560 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6562 child_scroll
->AddChild(occluder_layer
.Pass());
6563 scroll_layer
->AddChild(child_scroll
.Pass());
6567 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6568 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6571 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6572 gfx::Size
content_size(100, 100);
6573 SetupScrollAndContentsLayers(content_size
);
6575 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6577 int scroll_layer_id
= 2;
6578 LayerImpl
* scroll_layer
=
6579 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6581 int child_scroll_layer_id
= 7;
6582 scoped_ptr
<LayerImpl
> child_scroll
=
6583 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6584 child_scroll
->SetDrawsContent(false);
6586 scroll_layer
->AddChild(child_scroll
.Pass());
6590 // We should not have scrolled |child_scroll| even though we technically "hit"
6591 // it. The reason for this is that if the scrolling the scroll would not move
6592 // any layer that is a drawn RSLL member, then we can ignore the hit.
6594 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6595 // started scrolling the inner viewport.
6596 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6597 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6599 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6602 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6603 gfx::Size
content_size(100, 100);
6604 SetupScrollAndContentsLayers(content_size
);
6606 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6607 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6609 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6610 CreateScrollableLayer(7, content_size
, root
);
6611 invisible_scroll_layer
->SetDrawsContent(false);
6613 scoped_ptr
<LayerImpl
> child_layer
=
6614 LayerImpl::Create(host_impl_
->active_tree(), 8);
6615 child_layer
->SetDrawsContent(false);
6617 scoped_ptr
<LayerImpl
> grand_child_layer
=
6618 LayerImpl::Create(host_impl_
->active_tree(), 9);
6619 grand_child_layer
->SetDrawsContent(true);
6620 grand_child_layer
->SetBounds(content_size
);
6621 // Move the grand child so it's not hit by our test point.
6622 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6624 child_layer
->AddChild(grand_child_layer
.Pass());
6625 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6626 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6630 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6631 // a descendant which is a drawn RSLL member.
6632 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6633 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6635 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6638 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6639 // This test case is very similar to the one above with one key difference:
6640 // the invisible scroller has a scroll child that is indeed draw contents.
6641 // If we attempt to initiate a gesture scroll off of the visible scroll child
6642 // we should still start the scroll child.
6643 gfx::Size
content_size(100, 100);
6644 SetupScrollAndContentsLayers(content_size
);
6646 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6648 int scroll_layer_id
= 2;
6649 LayerImpl
* scroll_layer
=
6650 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6652 int scroll_child_id
= 6;
6653 scoped_ptr
<LayerImpl
> scroll_child
=
6654 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6655 scroll_child
->SetDrawsContent(true);
6656 scroll_child
->SetBounds(content_size
);
6657 // Move the scroll child so it's not hit by our test point.
6658 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6660 int invisible_scroll_layer_id
= 7;
6661 scoped_ptr
<LayerImpl
> invisible_scroll
=
6662 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6663 invisible_scroll
->SetDrawsContent(false);
6665 int container_id
= 8;
6666 scoped_ptr
<LayerImpl
> container
=
6667 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6669 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6670 scroll_children
->insert(scroll_child
.get());
6671 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6673 scroll_child
->SetScrollParent(invisible_scroll
.get());
6675 container
->AddChild(invisible_scroll
.Pass());
6676 container
->AddChild(scroll_child
.Pass());
6678 scroll_layer
->AddChild(container
.Pass());
6682 // We should have scrolled |child_scroll| even though it is invisible.
6683 // The reason for this is that if the scrolling the scroll would move a layer
6684 // that is a drawn RSLL member, then we should accept this hit.
6685 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6686 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6688 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6691 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6692 // to CompositorFrameMetadata after SwapBuffers();
6693 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6694 scoped_ptr
<SolidColorLayerImpl
> root
=
6695 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6696 root
->SetPosition(gfx::PointF());
6697 root
->SetBounds(gfx::Size(10, 10));
6698 root
->SetDrawsContent(true);
6699 root
->SetHasRenderSurface(true);
6701 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6703 FakeOutputSurface
* fake_output_surface
=
6704 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6706 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6707 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6708 EXPECT_TRUE(metadata_latency_before
.empty());
6710 ui::LatencyInfo latency_info
;
6711 latency_info
.AddLatencyNumber(
6712 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6713 scoped_ptr
<SwapPromise
> swap_promise(
6714 new LatencyInfoSwapPromise(latency_info
));
6715 host_impl_
->active_tree()->QueueSwapPromise(swap_promise
.Pass());
6716 host_impl_
->SetNeedsRedraw();
6718 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6719 LayerTreeHostImpl::FrameData frame
;
6720 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6721 host_impl_
->DrawLayers(&frame
);
6722 host_impl_
->DidDrawAllLayers(frame
);
6723 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6725 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6726 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6727 EXPECT_EQ(1u, metadata_latency_after
.size());
6728 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6729 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6732 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6733 int root_layer_id
= 1;
6734 scoped_ptr
<SolidColorLayerImpl
> root
=
6735 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6736 root
->SetPosition(gfx::PointF());
6737 root
->SetBounds(gfx::Size(10, 10));
6738 root
->SetDrawsContent(true);
6739 root
->SetHasRenderSurface(true);
6741 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6743 // Ensure the default frame selection bounds are empty.
6744 FakeOutputSurface
* fake_output_surface
=
6745 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6746 const ViewportSelection
& selection_before
=
6747 fake_output_surface
->last_sent_frame().metadata
.selection
;
6748 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
6749 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
6751 // Plumb the layer-local selection bounds.
6752 gfx::PointF
selection_top(5, 0);
6753 gfx::PointF
selection_bottom(5, 5);
6754 LayerSelection selection
;
6755 selection
.start
.type
= SELECTION_BOUND_CENTER
;
6756 selection
.start
.layer_id
= root_layer_id
;
6757 selection
.start
.edge_bottom
= selection_bottom
;
6758 selection
.start
.edge_top
= selection_top
;
6759 selection
.end
= selection
.start
;
6760 host_impl_
->active_tree()->RegisterSelection(selection
);
6762 // Trigger a draw-swap sequence.
6763 host_impl_
->SetNeedsRedraw();
6765 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6766 LayerTreeHostImpl::FrameData frame
;
6767 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6768 host_impl_
->DrawLayers(&frame
);
6769 host_impl_
->DidDrawAllLayers(frame
);
6770 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6772 // Ensure the selection bounds have propagated to the frame metadata.
6773 const ViewportSelection
& selection_after
=
6774 fake_output_surface
->last_sent_frame().metadata
.selection
;
6775 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
6776 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
6777 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
6778 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
6779 EXPECT_TRUE(selection_after
.start
.visible
);
6780 EXPECT_TRUE(selection_after
.start
.visible
);
6783 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
6785 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
6786 LayerTreeHostImpl
* layer_tree_host_impl
,
6787 int* set_needs_commit_count
,
6788 int* set_needs_redraw_count
,
6789 int* forward_to_main_count
)
6790 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
6791 set_needs_commit_count_(set_needs_commit_count
),
6792 set_needs_redraw_count_(set_needs_redraw_count
),
6793 forward_to_main_count_(forward_to_main_count
) {}
6795 ~SimpleSwapPromiseMonitor() override
{}
6797 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
6799 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
6801 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
6802 (*forward_to_main_count_
)++;
6806 int* set_needs_commit_count_
;
6807 int* set_needs_redraw_count_
;
6808 int* forward_to_main_count_
;
6811 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
6812 int set_needs_commit_count
= 0;
6813 int set_needs_redraw_count
= 0;
6814 int forward_to_main_count
= 0;
6817 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6818 new SimpleSwapPromiseMonitor(NULL
,
6820 &set_needs_commit_count
,
6821 &set_needs_redraw_count
,
6822 &forward_to_main_count
));
6823 host_impl_
->SetNeedsRedraw();
6824 EXPECT_EQ(0, set_needs_commit_count
);
6825 EXPECT_EQ(1, set_needs_redraw_count
);
6826 EXPECT_EQ(0, forward_to_main_count
);
6829 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6831 host_impl_
->SetNeedsRedraw();
6832 EXPECT_EQ(0, set_needs_commit_count
);
6833 EXPECT_EQ(1, set_needs_redraw_count
);
6834 EXPECT_EQ(0, forward_to_main_count
);
6837 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6838 new SimpleSwapPromiseMonitor(NULL
,
6840 &set_needs_commit_count
,
6841 &set_needs_redraw_count
,
6842 &forward_to_main_count
));
6843 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
6844 EXPECT_EQ(0, set_needs_commit_count
);
6845 EXPECT_EQ(2, set_needs_redraw_count
);
6846 EXPECT_EQ(0, forward_to_main_count
);
6850 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6851 new SimpleSwapPromiseMonitor(NULL
,
6853 &set_needs_commit_count
,
6854 &set_needs_redraw_count
,
6855 &forward_to_main_count
));
6856 // Empty damage rect won't signal the monitor.
6857 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
6858 EXPECT_EQ(0, set_needs_commit_count
);
6859 EXPECT_EQ(2, set_needs_redraw_count
);
6860 EXPECT_EQ(0, forward_to_main_count
);
6864 set_needs_commit_count
= 0;
6865 set_needs_redraw_count
= 0;
6866 forward_to_main_count
= 0;
6867 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6868 new SimpleSwapPromiseMonitor(NULL
,
6870 &set_needs_commit_count
,
6871 &set_needs_redraw_count
,
6872 &forward_to_main_count
));
6873 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
6875 // Scrolling normally should not trigger any forwarding.
6876 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6877 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6879 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6880 host_impl_
->ScrollEnd();
6882 EXPECT_EQ(0, set_needs_commit_count
);
6883 EXPECT_EQ(1, set_needs_redraw_count
);
6884 EXPECT_EQ(0, forward_to_main_count
);
6886 // Scrolling with a scroll handler should defer the swap to the main
6888 scroll_layer
->SetHaveScrollEventHandlers(true);
6889 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6890 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6892 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6893 host_impl_
->ScrollEnd();
6895 EXPECT_EQ(0, set_needs_commit_count
);
6896 EXPECT_EQ(2, set_needs_redraw_count
);
6897 EXPECT_EQ(1, forward_to_main_count
);
6901 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
6903 void SetUp() override
{
6904 LayerTreeSettings settings
= DefaultSettings();
6905 CreateHostImpl(settings
, CreateOutputSurface());
6906 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
6907 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
6908 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
6912 static const int top_controls_height_
;
6915 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
6917 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
6918 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6919 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6920 host_impl_
->Animate(base::TimeTicks());
6921 EXPECT_FALSE(did_request_redraw_
);
6924 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
6925 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6926 EXPECT_FALSE(did_request_redraw_
);
6927 host_impl_
->CreatePendingTree();
6928 host_impl_
->sync_tree()->set_top_controls_height(100);
6929 host_impl_
->ActivateSyncTree();
6930 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
6933 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6934 TopControlsStayFullyVisibleOnHeightChange
) {
6935 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6936 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6938 host_impl_
->CreatePendingTree();
6939 host_impl_
->sync_tree()->set_top_controls_height(0);
6940 host_impl_
->ActivateSyncTree();
6941 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6943 host_impl_
->CreatePendingTree();
6944 host_impl_
->sync_tree()->set_top_controls_height(50);
6945 host_impl_
->ActivateSyncTree();
6946 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6949 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
6950 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6951 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6952 host_impl_
->DidChangeTopControlsPosition();
6953 EXPECT_TRUE(did_request_animate_
);
6954 EXPECT_TRUE(did_request_redraw_
);
6957 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
6958 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6959 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6960 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6961 BOTH
, SHOWN
, false);
6964 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6965 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6966 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6967 EXPECT_EQ(gfx::Vector2dF().ToString(),
6968 scroll_layer
->CurrentScrollOffset().ToString());
6970 // Scroll just the top controls and verify that the scroll succeeds.
6971 const float residue
= 10;
6972 float offset
= top_controls_height_
- residue
;
6974 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6975 EXPECT_FLOAT_EQ(-offset
,
6976 host_impl_
->top_controls_manager()->ControlsTopOffset());
6977 EXPECT_EQ(gfx::Vector2dF().ToString(),
6978 scroll_layer
->CurrentScrollOffset().ToString());
6980 // Scroll across the boundary
6981 const float content_scroll
= 20;
6982 offset
= residue
+ content_scroll
;
6984 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6985 EXPECT_EQ(-top_controls_height_
,
6986 host_impl_
->top_controls_manager()->ControlsTopOffset());
6987 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
6988 scroll_layer
->CurrentScrollOffset().ToString());
6990 // Now scroll back to the top of the content
6991 offset
= -content_scroll
;
6993 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6994 EXPECT_EQ(-top_controls_height_
,
6995 host_impl_
->top_controls_manager()->ControlsTopOffset());
6996 EXPECT_EQ(gfx::Vector2dF().ToString(),
6997 scroll_layer
->CurrentScrollOffset().ToString());
6999 // And scroll the top controls completely into view
7000 offset
= -top_controls_height_
;
7002 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7003 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7004 EXPECT_EQ(gfx::Vector2dF().ToString(),
7005 scroll_layer
->CurrentScrollOffset().ToString());
7007 // And attempt to scroll past the end
7009 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7010 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7011 EXPECT_EQ(gfx::Vector2dF().ToString(),
7012 scroll_layer
->CurrentScrollOffset().ToString());
7014 host_impl_
->ScrollEnd();
7017 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
7018 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7019 host_impl_
->SetViewportSize(gfx::Size(100, 200));
7020 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7021 BOTH
, SHOWN
, false);
7024 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7025 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7026 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7027 EXPECT_EQ(gfx::Vector2dF().ToString(),
7028 scroll_layer
->CurrentScrollOffset().ToString());
7030 // Scroll the top controls partially.
7031 const float residue
= 35;
7032 float offset
= top_controls_height_
- residue
;
7034 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7035 EXPECT_FLOAT_EQ(-offset
,
7036 host_impl_
->top_controls_manager()->ControlsTopOffset());
7037 EXPECT_EQ(gfx::Vector2dF().ToString(),
7038 scroll_layer
->CurrentScrollOffset().ToString());
7040 did_request_redraw_
= false;
7041 did_request_animate_
= false;
7042 did_request_commit_
= false;
7044 // End the scroll while the controls are still offset from their limit.
7045 host_impl_
->ScrollEnd();
7046 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7047 EXPECT_TRUE(did_request_animate_
);
7048 EXPECT_TRUE(did_request_redraw_
);
7049 EXPECT_FALSE(did_request_commit_
);
7051 // The top controls should properly animate until finished, despite the scroll
7052 // offset being at the origin.
7053 base::TimeTicks animation_time
= base::TimeTicks::Now();
7054 while (did_request_animate_
) {
7055 did_request_redraw_
= false;
7056 did_request_animate_
= false;
7057 did_request_commit_
= false;
7060 host_impl_
->top_controls_manager()->ControlsTopOffset();
7062 animation_time
+= base::TimeDelta::FromMilliseconds(5);
7063 host_impl_
->Animate(animation_time
);
7064 EXPECT_EQ(gfx::Vector2dF().ToString(),
7065 scroll_layer
->CurrentScrollOffset().ToString());
7068 host_impl_
->top_controls_manager()->ControlsTopOffset();
7070 // No commit is needed as the controls are animating the content offset,
7071 // not the scroll offset.
7072 EXPECT_FALSE(did_request_commit_
);
7074 if (new_offset
!= old_offset
)
7075 EXPECT_TRUE(did_request_redraw_
);
7077 if (new_offset
!= 0) {
7078 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
7079 EXPECT_TRUE(did_request_animate_
);
7082 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7085 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
7086 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7087 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7088 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7089 BOTH
, SHOWN
, false);
7090 float initial_scroll_offset
= 50;
7091 scroll_layer
->PushScrollOffsetFromMainThread(
7092 gfx::ScrollOffset(0, initial_scroll_offset
));
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(0, initial_scroll_offset
).ToString(),
7099 scroll_layer
->CurrentScrollOffset().ToString());
7101 // Scroll the top controls partially.
7102 const float residue
= 15;
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(0, initial_scroll_offset
).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 the 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 // Animate the top controls to the limit.
7123 base::TimeTicks animation_time
= base::TimeTicks::Now();
7124 while (did_request_animate_
) {
7125 did_request_redraw_
= false;
7126 did_request_animate_
= false;
7127 did_request_commit_
= false;
7130 host_impl_
->top_controls_manager()->ControlsTopOffset();
7132 animation_time
+= base::TimeDelta::FromMilliseconds(5);
7133 host_impl_
->Animate(animation_time
);
7136 host_impl_
->top_controls_manager()->ControlsTopOffset();
7138 if (new_offset
!= old_offset
) {
7139 EXPECT_TRUE(did_request_redraw_
);
7140 EXPECT_TRUE(did_request_commit_
);
7143 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7144 EXPECT_EQ(-top_controls_height_
,
7145 host_impl_
->top_controls_manager()->ControlsTopOffset());
7148 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7149 TopControlsAnimationAfterMainThreadFlingStopped
) {
7150 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7151 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7152 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7154 float initial_scroll_offset
= 50;
7155 scroll_layer
->PushScrollOffsetFromMainThread(
7156 gfx::ScrollOffset(0, initial_scroll_offset
));
7159 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7160 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7161 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7162 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7163 scroll_layer
->CurrentScrollOffset().ToString());
7165 // Scroll the top controls partially.
7166 const float residue
= 15;
7167 float offset
= top_controls_height_
- residue
;
7169 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7170 EXPECT_FLOAT_EQ(-offset
,
7171 host_impl_
->top_controls_manager()->ControlsTopOffset());
7172 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7173 scroll_layer
->CurrentScrollOffset().ToString());
7175 did_request_redraw_
= false;
7176 did_request_animate_
= false;
7177 did_request_commit_
= false;
7179 // End the fling while the controls are still offset from the limit.
7180 host_impl_
->MainThreadHasStoppedFlinging();
7181 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7182 EXPECT_TRUE(did_request_animate_
);
7183 EXPECT_TRUE(did_request_redraw_
);
7184 EXPECT_FALSE(did_request_commit_
);
7186 // Animate the top controls to the limit.
7187 base::TimeTicks animation_time
= base::TimeTicks::Now();
7188 while (did_request_animate_
) {
7189 did_request_redraw_
= false;
7190 did_request_animate_
= false;
7191 did_request_commit_
= false;
7193 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7195 animation_time
+= base::TimeDelta::FromMilliseconds(5);
7196 host_impl_
->Animate(animation_time
);
7198 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7200 if (new_offset
!= old_offset
) {
7201 EXPECT_TRUE(did_request_redraw_
);
7202 EXPECT_TRUE(did_request_commit_
);
7205 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7206 EXPECT_EQ(-top_controls_height_
,
7207 host_impl_
->top_controls_manager()->ControlsTopOffset());
7210 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7211 TopControlsScrollDeltaInOverScroll
) {
7212 // test varifies that the overscroll delta should not have accumulated in
7213 // the top controls if we do a hide and show without releasing finger.
7215 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7216 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7217 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7221 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7222 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7223 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7227 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7228 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7229 EXPECT_EQ(gfx::Vector2dF().ToString(),
7230 scroll_layer
->CurrentScrollOffset().ToString());
7233 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7234 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7235 scroll_layer
->CurrentScrollOffset().ToString());
7238 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7240 // Should have fully scrolled
7241 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7242 scroll_layer
->CurrentScrollOffset().ToString());
7244 float overscrollamount
= 10;
7246 // Overscroll the content
7248 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7250 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7251 scroll_layer
->CurrentScrollOffset().ToString());
7252 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7253 host_impl_
->accumulated_root_overscroll().ToString());
7255 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7257 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7258 scroll_layer
->CurrentScrollOffset().ToString());
7259 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7262 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7263 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7264 scroll_layer
->CurrentScrollOffset().ToString());
7266 // Top controls should be fully visible
7267 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7269 host_impl_
->ScrollEnd();
7272 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7274 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7275 const gfx::Size
& outer_viewport
,
7276 const gfx::Size
& inner_viewport
) {
7277 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7278 const int kOuterViewportClipLayerId
= 6;
7279 const int kOuterViewportScrollLayerId
= 7;
7280 const int kInnerViewportScrollLayerId
= 2;
7281 const int kInnerViewportClipLayerId
= 4;
7282 const int kPageScaleLayerId
= 5;
7284 scoped_ptr
<LayerImpl
> inner_scroll
=
7285 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7286 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7287 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7289 scoped_ptr
<LayerImpl
> inner_clip
=
7290 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7291 inner_clip
->SetBounds(inner_viewport
);
7293 scoped_ptr
<LayerImpl
> page_scale
=
7294 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7296 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7297 inner_scroll
->SetBounds(outer_viewport
);
7298 inner_scroll
->SetPosition(gfx::PointF());
7300 scoped_ptr
<LayerImpl
> outer_clip
=
7301 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7302 outer_clip
->SetBounds(outer_viewport
);
7303 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7305 scoped_ptr
<LayerImpl
> outer_scroll
=
7306 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7307 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7308 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7309 outer_scroll
->SetBounds(content_size
);
7310 outer_scroll
->SetPosition(gfx::PointF());
7312 scoped_ptr
<LayerImpl
> contents
=
7313 LayerImpl::Create(layer_tree_impl
, 8);
7314 contents
->SetDrawsContent(true);
7315 contents
->SetBounds(content_size
);
7316 contents
->SetPosition(gfx::PointF());
7318 outer_scroll
->AddChild(contents
.Pass());
7319 outer_clip
->AddChild(outer_scroll
.Pass());
7320 inner_scroll
->AddChild(outer_clip
.Pass());
7321 page_scale
->AddChild(inner_scroll
.Pass());
7322 inner_clip
->AddChild(page_scale
.Pass());
7324 inner_clip
->SetHasRenderSurface(true);
7325 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7326 layer_tree_impl
->SetViewportLayersFromIds(
7327 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7328 kOuterViewportScrollLayerId
);
7330 host_impl_
->active_tree()->DidBecomeActive();
7334 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7335 gfx::Size content_size
= gfx::Size(100, 160);
7336 gfx::Size outer_viewport
= gfx::Size(50, 80);
7337 gfx::Size inner_viewport
= gfx::Size(25, 40);
7339 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7341 TestScrollOffsetDelegate scroll_delegate
;
7342 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7344 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7345 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7348 gfx::ScrollOffset inner_expected
;
7349 gfx::ScrollOffset outer_expected
;
7350 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7351 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7353 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7355 scroll_delegate
.set_getter_return_value(current_offset
);
7356 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
7357 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7358 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7360 // Outer viewport scrolls first. Then the rest is applied to the inner
7362 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7363 inner_scroll
->CurrentScrollOffset());
7364 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7365 outer_scroll
->CurrentScrollOffset());
7369 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7370 gfx::Size content_size
= gfx::Size(100, 160);
7371 gfx::Size outer_viewport
= gfx::Size(50, 80);
7372 gfx::Size inner_viewport
= gfx::Size(25, 40);
7374 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7376 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7377 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7380 gfx::Vector2dF inner_expected
;
7381 gfx::Vector2dF outer_expected
;
7382 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7383 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7385 // Make sure the fling goes to the outer viewport first
7386 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7387 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7388 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7390 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7391 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7392 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7394 host_impl_
->ScrollEnd();
7396 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7397 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7399 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7400 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7401 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7402 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7404 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7405 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7407 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7408 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7410 host_impl_
->ScrollEnd();
7412 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7413 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7417 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7418 DiagonalScrollBubblesPerfectlyToInner
) {
7419 gfx::Size content_size
= gfx::Size(100, 160);
7420 gfx::Size outer_viewport
= gfx::Size(50, 80);
7421 gfx::Size inner_viewport
= gfx::Size(25, 40);
7423 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7425 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7426 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7429 gfx::Vector2dF inner_expected
;
7430 gfx::Vector2dF outer_expected
;
7431 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7432 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7434 // Make sure the scroll goes to the outer viewport first.
7435 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7436 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7437 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7438 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7439 InputHandler::GESTURE
));
7441 // Scroll near the edge of the outer viewport.
7442 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7443 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7444 outer_expected
+= scroll_delta
;
7445 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7446 InputHandler::GESTURE
));
7448 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7449 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7451 // Now diagonal scroll across the outer viewport boundary in a single event.
7452 // The entirety of the scroll should be consumed, as bubbling between inner
7453 // and outer viewport layers is perfect.
7454 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7455 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7456 InputHandler::GESTURE
));
7457 outer_expected
+= scroll_delta
;
7458 inner_expected
+= scroll_delta
;
7459 host_impl_
->ScrollEnd();
7460 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7461 gfx::Point(), InputHandler::GESTURE
));
7463 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7464 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7468 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7469 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7470 gfx::Size content_size
= gfx::Size(100, 160);
7471 gfx::Size outer_viewport
= gfx::Size(50, 80);
7472 gfx::Size inner_viewport
= gfx::Size(25, 40);
7474 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7476 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7477 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7479 scoped_ptr
<LayerImpl
> child
=
7480 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7481 LayerImpl
* child_scroll
= child
.get();
7482 outer_scroll
->children()[0]->AddChild(child
.Pass());
7486 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7488 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7489 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7490 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7491 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7492 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7493 InputHandler::GESTURE
));
7495 // The child should have scrolled up to its limit.
7496 scroll_info
= host_impl_
->ProcessScrollDeltas();
7497 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7499 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7500 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7502 // The first |ScrollBy| after the fling should re-lock the scrolling
7503 // layer to the first layer that scrolled, the inner viewport scroll layer.
7504 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7505 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7506 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7507 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7508 InputHandler::GESTURE
));
7510 // The inner viewport should have scrolled up to its limit.
7511 scroll_info
= host_impl_
->ProcessScrollDeltas();
7512 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7514 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7516 ScrollInfoContains(*scroll_info
, inner_scroll
->id(), scroll_delta
));
7518 // As the locked layer is at its limit, no further scrolling can occur.
7519 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7520 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7521 host_impl_
->ScrollEnd();
7522 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7523 gfx::Point(), InputHandler::GESTURE
));
7527 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7528 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest
) {
7529 gfx::Size content_size
= gfx::Size(100, 160);
7530 gfx::Size outer_viewport
= gfx::Size(50, 80);
7531 gfx::Size inner_viewport
= gfx::Size(25, 40);
7533 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7535 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7536 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7538 scoped_ptr
<LayerImpl
> child
=
7539 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7540 LayerImpl
* child_scroll
= child
.get();
7541 outer_scroll
->children()[0]->AddChild(child
.Pass());
7545 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7546 host_impl_
->RootScrollBegin(InputHandler::GESTURE
));
7547 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7548 host_impl_
->ScrollEnd();
7549 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7550 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7551 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7552 host_impl_
->ScrollEnd();
7555 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7557 void SetUp() override
{
7558 LayerTreeSettings settings
= DefaultSettings();
7559 settings
.max_memory_for_prepaint_percentage
= 50;
7560 CreateHostImpl(settings
, CreateOutputSurface());
7564 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7565 // Set up a memory policy and percentages which could cause
7566 // 32-bit integer overflows.
7567 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7569 // Verify implicit limits are calculated correctly with no overflows
7570 host_impl_
->SetMemoryPolicy(mem_policy
);
7571 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7572 300u * 1024u * 1024u);
7573 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7574 150u * 1024u * 1024u);
7577 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7578 const gfx::Size
layer_size(100, 100);
7579 gfx::Transform external_transform
;
7580 const gfx::Rect
external_viewport(layer_size
);
7581 const gfx::Rect
external_clip(layer_size
);
7582 const bool resourceless_software_draw
= false;
7583 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7585 host_impl_
->SetExternalDrawConstraints(external_transform
,
7590 resourceless_software_draw
);
7592 EXPECT_TRANSFORMATION_MATRIX_EQ(
7593 external_transform
, layer
->draw_properties().target_space_transform
);
7595 external_transform
.Translate(20, 20);
7596 host_impl_
->SetExternalDrawConstraints(external_transform
,
7601 resourceless_software_draw
);
7603 EXPECT_TRANSFORMATION_MATRIX_EQ(
7604 external_transform
, layer
->draw_properties().target_space_transform
);
7607 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7608 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7611 base::TimeTicks start_time
=
7612 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7614 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7615 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7617 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7619 host_impl_
->Animate(start_time
);
7620 host_impl_
->UpdateAnimationState(true);
7622 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7624 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(50));
7625 host_impl_
->UpdateAnimationState(true);
7627 float y
= scrolling_layer
->CurrentScrollOffset().y();
7628 EXPECT_TRUE(y
> 1 && y
< 49);
7631 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7632 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7634 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(200));
7635 host_impl_
->UpdateAnimationState(true);
7637 y
= scrolling_layer
->CurrentScrollOffset().y();
7638 EXPECT_TRUE(y
> 50 && y
< 100);
7639 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7641 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(250));
7642 host_impl_
->UpdateAnimationState(true);
7644 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7645 scrolling_layer
->CurrentScrollOffset());
7646 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7649 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
7650 host_impl_
->CreatePendingTree();
7652 Region empty_invalidation
;
7653 scoped_refptr
<RasterSource
> pile_with_tiles(
7654 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7655 gfx::Size(10, 10)));
7657 scoped_ptr
<FakePictureLayerImpl
> layer
=
7658 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
7659 layer
->SetBounds(gfx::Size(10, 10));
7660 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
7661 layer
->SetDrawsContent(true);
7662 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
7663 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
7664 layer
->tilings()->tiling_at(0)->set_resolution(
7665 TileResolution::HIGH_RESOLUTION
);
7666 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
7667 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
7668 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
7669 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
7671 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
7672 host_impl_
->pending_tree()->root_layer());
7674 root_layer
->set_has_valid_tile_priorities(true);
7675 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
7676 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7677 RasterTilePriorityQueue::Type::ALL
);
7678 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
7680 root_layer
->set_has_valid_tile_priorities(false);
7681 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
7682 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7683 RasterTilePriorityQueue::Type::ALL
);
7684 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
7687 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
7688 host_impl_
->CreatePendingTree();
7689 host_impl_
->ActivateSyncTree();
7690 host_impl_
->CreatePendingTree();
7692 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
7694 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
7695 FakePictureLayerImpl::Create(pending_tree
, 10);
7696 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
7697 pending_tree
->SetRootLayer(pending_layer
.Pass());
7698 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
7700 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
7701 pending_tree
->DidBecomeActive();
7702 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7704 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
7705 FakePictureLayerImpl::Create(pending_tree
, 11);
7706 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
7707 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
7708 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
7710 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7711 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
7712 pending_tree
->DidBecomeActive();
7713 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7714 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7716 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
7717 FakePictureLayerImpl::Create(pending_tree
, 12);
7718 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
7719 FakePictureLayerImpl::Create(pending_tree
, 13);
7720 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
7721 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
7722 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
7723 ASSERT_EQ(raw_replica_mask_layer
,
7724 raw_pending_layer
->replica_layer()->mask_layer());
7726 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7727 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7728 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
7729 pending_tree
->DidBecomeActive();
7730 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
7731 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
7732 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
7735 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
7736 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7737 host_impl_
->SetViewportSize(gfx::Size(50, 50));
7740 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
7742 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
7743 float page_scale_factor
= 1.f
;
7745 // The scroll deltas should have the page scale factor applied.
7747 host_impl_
->active_tree()->PushPageScaleFromMainThread(
7748 page_scale_factor
, min_page_scale
, max_page_scale
);
7749 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
7750 scroll_layer
->SetScrollDelta(gfx::Vector2d());
7752 float page_scale_delta
= 2.f
;
7753 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
7754 host_impl_
->PinchGestureBegin();
7755 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
7756 host_impl_
->PinchGestureEnd();
7757 host_impl_
->ScrollEnd();
7759 gfx::Vector2dF
scroll_delta(0, 5);
7760 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7761 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7762 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
7764 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7765 host_impl_
->ScrollEnd();
7766 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7767 scroll_layer
->CurrentScrollOffset());
7771 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
7773 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7774 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
7777 int num_lost_surfaces_
;
7780 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
7781 // Really we just need at least one client notification each time
7782 // we go from having a valid output surface to not having a valid output
7784 EXPECT_EQ(0, num_lost_surfaces_
);
7785 host_impl_
->DidLoseOutputSurface();
7786 EXPECT_EQ(1, num_lost_surfaces_
);
7787 host_impl_
->DidLoseOutputSurface();
7788 EXPECT_LE(1, num_lost_surfaces_
);
7791 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
7792 LayerTreeHostImpl::FrameData frame
;
7793 frame
.render_passes
.push_back(RenderPass::Create());
7794 RenderPass
* pass3
= frame
.render_passes
.back();
7795 frame
.render_passes
.push_back(RenderPass::Create());
7796 RenderPass
* pass2
= frame
.render_passes
.back();
7797 frame
.render_passes
.push_back(RenderPass::Create());
7798 RenderPass
* pass1
= frame
.render_passes
.back();
7800 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7801 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7802 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7804 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7805 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7806 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7808 // Add a quad to each pass so they aren't empty.
7809 SolidColorDrawQuad
* color_quad
;
7810 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7811 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7812 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7813 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7814 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7815 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7817 // pass3 is referenced by pass2.
7818 RenderPassDrawQuad
* rpdq
=
7819 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7820 rpdq
->material
= DrawQuad::RENDER_PASS
;
7821 rpdq
->render_pass_id
= pass3
->id
;
7823 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7824 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7825 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7826 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7827 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7828 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7829 EXPECT_EQ(1u, frame
.render_passes
.size());
7830 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7833 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
7834 LayerTreeHostImpl::FrameData frame
;
7835 frame
.render_passes
.push_back(RenderPass::Create());
7836 RenderPass
* pass3
= frame
.render_passes
.back();
7837 frame
.render_passes
.push_back(RenderPass::Create());
7838 RenderPass
* pass2
= frame
.render_passes
.back();
7839 frame
.render_passes
.push_back(RenderPass::Create());
7840 RenderPass
* pass1
= frame
.render_passes
.back();
7842 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7843 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7844 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7846 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7847 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7848 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7850 // pass1 is not empty, but pass2 and pass3 are.
7851 SolidColorDrawQuad
* color_quad
;
7852 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7853 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7855 // pass3 is referenced by pass2.
7856 RenderPassDrawQuad
* rpdq
=
7857 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7858 rpdq
->material
= DrawQuad::RENDER_PASS
;
7859 rpdq
->render_pass_id
= pass3
->id
;
7861 // pass2 is referenced by pass1.
7862 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7863 rpdq
->material
= DrawQuad::RENDER_PASS
;
7864 rpdq
->render_pass_id
= pass2
->id
;
7866 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7867 // should be removed.
7868 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7869 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7870 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7871 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7872 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7873 EXPECT_EQ(1u, frame
.render_passes
.size());
7874 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7875 // The RenderPassDrawQuad should be removed from pass1.
7876 EXPECT_EQ(1u, pass1
->quad_list
.size());
7877 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
7880 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
7881 LayerTreeHostImpl::FrameData frame
;
7882 frame
.render_passes
.push_back(RenderPass::Create());
7883 RenderPass
* pass3
= frame
.render_passes
.back();
7884 frame
.render_passes
.push_back(RenderPass::Create());
7885 RenderPass
* pass2
= frame
.render_passes
.back();
7886 frame
.render_passes
.push_back(RenderPass::Create());
7887 RenderPass
* pass1
= frame
.render_passes
.back();
7889 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7890 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7891 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7893 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7894 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7895 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7897 // pass3 is referenced by pass2.
7898 RenderPassDrawQuad
* rpdq
=
7899 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7900 rpdq
->material
= DrawQuad::RENDER_PASS
;
7901 rpdq
->render_pass_id
= pass3
->id
;
7903 // pass2 is referenced by pass1.
7904 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7905 rpdq
->material
= DrawQuad::RENDER_PASS
;
7906 rpdq
->render_pass_id
= pass2
->id
;
7908 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7909 // should be removed. Then pass1 is empty too, but it's the root so it should
7911 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7912 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7913 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7914 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7915 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7916 EXPECT_EQ(1u, frame
.render_passes
.size());
7917 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7918 // The RenderPassDrawQuad should be removed from pass1.
7919 EXPECT_EQ(0u, pass1
->quad_list
.size());
7922 class FakeVideoFrameController
: public VideoFrameController
{
7924 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
7925 begin_frame_args_
= args
;
7926 did_draw_frame_
= false;
7929 void DidDrawFrame() override
{ did_draw_frame_
= true; }
7931 const BeginFrameArgs
& begin_frame_args() const { return begin_frame_args_
; }
7933 bool did_draw_frame() const { return did_draw_frame_
; }
7936 BeginFrameArgs begin_frame_args_
;
7937 bool did_draw_frame_
= false;
7940 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
7941 host_impl_
->DidFinishImplFrame();
7943 BeginFrameArgs begin_frame_args
=
7944 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7945 FakeVideoFrameController controller
;
7947 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7948 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7949 host_impl_
->AddVideoFrameController(&controller
);
7950 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7951 host_impl_
->DidFinishImplFrame();
7953 EXPECT_FALSE(controller
.did_draw_frame());
7954 LayerTreeHostImpl::FrameData frame
;
7955 host_impl_
->DidDrawAllLayers(frame
);
7956 EXPECT_TRUE(controller
.did_draw_frame());
7958 controller
.OnBeginFrame(begin_frame_args
);
7959 EXPECT_FALSE(controller
.did_draw_frame());
7960 host_impl_
->RemoveVideoFrameController(&controller
);
7961 host_impl_
->DidDrawAllLayers(frame
);
7962 EXPECT_FALSE(controller
.did_draw_frame());
7965 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
7966 host_impl_
->DidFinishImplFrame();
7968 BeginFrameArgs begin_frame_args
=
7969 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7970 FakeVideoFrameController controller
;
7972 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7973 host_impl_
->DidFinishImplFrame();
7975 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7976 host_impl_
->AddVideoFrameController(&controller
);
7977 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7979 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7980 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7981 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7982 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7984 EXPECT_FALSE(controller
.did_draw_frame());
7985 LayerTreeHostImpl::FrameData frame
;
7986 host_impl_
->DidDrawAllLayers(frame
);
7987 EXPECT_TRUE(controller
.did_draw_frame());
7989 controller
.OnBeginFrame(begin_frame_args
);
7990 EXPECT_FALSE(controller
.did_draw_frame());
7991 host_impl_
->RemoveVideoFrameController(&controller
);
7992 host_impl_
->DidDrawAllLayers(frame
);
7993 EXPECT_FALSE(controller
.did_draw_frame());
7996 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
7997 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7999 host_impl_
->SetHasGpuRasterizationTrigger(true);
8000 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8001 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
8002 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8004 host_impl_
->SetHasGpuRasterizationTrigger(false);
8005 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8006 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
8007 host_impl_
->gpu_rasterization_status());
8008 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8010 host_impl_
->SetHasGpuRasterizationTrigger(true);
8011 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8012 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
8013 host_impl_
->gpu_rasterization_status());
8014 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8015 EXPECT_FALSE(host_impl_
->use_msaa());
8017 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
8018 TestWebGraphicsContext3D::Create();
8019 context_with_msaa
->SetMaxSamples(8);
8021 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
8022 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
8023 EXPECT_TRUE(CreateHostImpl(
8024 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
8025 host_impl_
->SetHasGpuRasterizationTrigger(true);
8026 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8027 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
8028 host_impl_
->gpu_rasterization_status());
8029 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8030 EXPECT_TRUE(host_impl_
->use_msaa());
8032 LayerTreeSettings settings
= DefaultSettings();
8033 settings
.gpu_rasterization_enabled
= false;
8034 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8035 host_impl_
->SetHasGpuRasterizationTrigger(true);
8036 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8037 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
8038 host_impl_
->gpu_rasterization_status());
8039 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8041 settings
.gpu_rasterization_forced
= true;
8042 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8044 host_impl_
->SetHasGpuRasterizationTrigger(false);
8045 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8046 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
8047 host_impl_
->gpu_rasterization_status());
8048 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8051 // A mock output surface which lets us detect calls to ForceReclaimResources.
8052 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
8054 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
8055 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8056 TestContextProvider::Create(), TestContextProvider::Create(), false));
8059 MOCK_METHOD0(ForceReclaimResources
, void());
8062 MockReclaimResourcesOutputSurface(
8063 scoped_refptr
<ContextProvider
> context_provider
,
8064 scoped_refptr
<ContextProvider
> worker_context_provider
,
8065 bool delegated_rendering
)
8066 : FakeOutputSurface(context_provider
,
8067 worker_context_provider
,
8068 delegated_rendering
) {}
8071 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8072 // being reclaimed to block drawing between BeginCommit / Swap. This test
8073 // ensures that BeginCommit triggers ForceReclaimResources. See
8074 // crbug.com/489515.
8075 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
8076 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
8077 MockReclaimResourcesOutputSurface::Create3d());
8078 // Hold an unowned pointer to the output surface to use for mock expectations.
8079 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
8081 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
8082 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
8083 host_impl_
->BeginCommit();