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/animation/transform_operations.h"
18 #include "cc/base/math_util.h"
19 #include "cc/input/page_scale_animation.h"
20 #include "cc/input/top_controls_manager.h"
21 #include "cc/layers/append_quads_data.h"
22 #include "cc/layers/delegated_renderer_layer_impl.h"
23 #include "cc/layers/heads_up_display_layer_impl.h"
24 #include "cc/layers/io_surface_layer_impl.h"
25 #include "cc/layers/layer_impl.h"
26 #include "cc/layers/painted_scrollbar_layer_impl.h"
27 #include "cc/layers/render_surface_impl.h"
28 #include "cc/layers/solid_color_layer_impl.h"
29 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
30 #include "cc/layers/texture_layer_impl.h"
31 #include "cc/layers/video_layer_impl.h"
32 #include "cc/layers/viewport.h"
33 #include "cc/output/begin_frame_args.h"
34 #include "cc/output/compositor_frame_ack.h"
35 #include "cc/output/compositor_frame_metadata.h"
36 #include "cc/output/copy_output_request.h"
37 #include "cc/output/copy_output_result.h"
38 #include "cc/output/gl_renderer.h"
39 #include "cc/output/latency_info_swap_promise.h"
40 #include "cc/quads/render_pass_draw_quad.h"
41 #include "cc/quads/solid_color_draw_quad.h"
42 #include "cc/quads/texture_draw_quad.h"
43 #include "cc/quads/tile_draw_quad.h"
44 #include "cc/test/animation_test_common.h"
45 #include "cc/test/begin_frame_args_test.h"
46 #include "cc/test/fake_layer_tree_host_impl.h"
47 #include "cc/test/fake_output_surface.h"
48 #include "cc/test/fake_output_surface_client.h"
49 #include "cc/test/fake_picture_layer_impl.h"
50 #include "cc/test/fake_picture_pile_impl.h"
51 #include "cc/test/fake_proxy.h"
52 #include "cc/test/fake_video_frame_provider.h"
53 #include "cc/test/geometry_test_utils.h"
54 #include "cc/test/gpu_rasterization_enabled_settings.h"
55 #include "cc/test/layer_test_common.h"
56 #include "cc/test/layer_tree_test.h"
57 #include "cc/test/test_gpu_memory_buffer_manager.h"
58 #include "cc/test/test_shared_bitmap_manager.h"
59 #include "cc/test/test_task_graph_runner.h"
60 #include "cc/test/test_web_graphics_context_3d.h"
61 #include "cc/trees/layer_tree_impl.h"
62 #include "cc/trees/single_thread_proxy.h"
63 #include "media/base/media.h"
64 #include "testing/gmock/include/gmock/gmock.h"
65 #include "testing/gtest/include/gtest/gtest.h"
66 #include "third_party/skia/include/core/SkMallocPixelRef.h"
67 #include "ui/gfx/geometry/rect_conversions.h"
68 #include "ui/gfx/geometry/size_conversions.h"
69 #include "ui/gfx/geometry/vector2d_conversions.h"
71 using ::testing::Mock
;
72 using ::testing::Return
;
73 using ::testing::AnyNumber
;
74 using ::testing::AtLeast
;
76 using media::VideoFrame
;
81 class LayerTreeHostImplTest
: public testing::Test
,
82 public LayerTreeHostImplClient
{
84 LayerTreeHostImplTest()
85 : proxy_(base::ThreadTaskRunnerHandle::Get(),
86 base::ThreadTaskRunnerHandle::Get()),
87 always_impl_thread_(&proxy_
),
88 always_main_thread_blocked_(&proxy_
),
89 on_can_draw_state_changed_called_(false),
90 did_notify_ready_to_activate_(false),
91 did_request_commit_(false),
92 did_request_redraw_(false),
93 did_request_animate_(false),
94 did_request_prepare_tiles_(false),
95 did_complete_page_scale_animation_(false),
96 reduce_memory_result_(true) {
97 media::InitializeMediaLibrary();
100 LayerTreeSettings
DefaultSettings() {
101 LayerTreeSettings settings
;
102 settings
.minimum_occlusion_tracking_size
= gfx::Size();
103 settings
.renderer_settings
.texture_id_allocation_chunk_size
= 1;
104 settings
.gpu_rasterization_enabled
= true;
108 void SetUp() override
{
109 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
112 void TearDown() override
{}
114 void UpdateRendererCapabilitiesOnImplThread() override
{}
115 void DidLoseOutputSurfaceOnImplThread() override
{}
116 void CommitVSyncParameters(base::TimeTicks timebase
,
117 base::TimeDelta interval
) override
{}
118 void SetEstimatedParentDrawTime(base::TimeDelta draw_time
) override
{}
119 void SetMaxSwapsPendingOnImplThread(int max
) override
{}
120 void DidSwapBuffersOnImplThread() override
{}
121 void DidSwapBuffersCompleteOnImplThread() override
{}
122 void OnCanDrawStateChanged(bool can_draw
) override
{
123 on_can_draw_state_changed_called_
= true;
125 void NotifyReadyToActivate() override
{
126 did_notify_ready_to_activate_
= true;
127 host_impl_
->ActivateSyncTree();
129 void NotifyReadyToDraw() override
{}
130 void SetNeedsRedrawOnImplThread() override
{ did_request_redraw_
= true; }
131 void SetNeedsRedrawRectOnImplThread(const gfx::Rect
& damage_rect
) override
{
132 did_request_redraw_
= true;
134 void SetNeedsAnimateOnImplThread() override
{ did_request_animate_
= true; }
135 void SetNeedsPrepareTilesOnImplThread() override
{
136 did_request_prepare_tiles_
= true;
138 void SetNeedsCommitOnImplThread() override
{ did_request_commit_
= true; }
139 void SetVideoNeedsBeginFrames(bool needs_begin_frames
) override
{}
140 void PostAnimationEventsToMainThreadOnImplThread(
141 scoped_ptr
<AnimationEventsVector
> events
) override
{}
142 bool IsInsideDraw() override
{ return false; }
143 void RenewTreePriority() override
{}
144 void PostDelayedAnimationTaskOnImplThread(const base::Closure
& task
,
145 base::TimeDelta delay
) override
{
146 animation_task_
= task
;
147 requested_animation_delay_
= delay
;
149 void DidActivateSyncTree() override
{}
150 void WillPrepareTiles() override
{}
151 void DidPrepareTiles() override
{}
152 void DidCompletePageScaleAnimationOnImplThread() override
{
153 did_complete_page_scale_animation_
= true;
155 void OnDrawForOutputSurface() override
{}
156 void PostFrameTimingEventsOnImplThread(
157 scoped_ptr
<FrameTimingTracker::CompositeTimingSet
> composite_events
,
158 scoped_ptr
<FrameTimingTracker::MainFrameTimingSet
> main_frame_events
)
161 void set_reduce_memory_result(bool reduce_memory_result
) {
162 reduce_memory_result_
= reduce_memory_result
;
165 virtual bool CreateHostImpl(const LayerTreeSettings
& settings
,
166 scoped_ptr
<OutputSurface
> output_surface
) {
167 host_impl_
= LayerTreeHostImpl::Create(
168 settings
, this, &proxy_
, &stats_instrumentation_
,
169 &shared_bitmap_manager_
, &gpu_memory_buffer_manager_
,
170 &task_graph_runner_
, 0);
171 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
172 host_impl_
->SetViewportSize(gfx::Size(10, 10));
173 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
174 // Set the BeginFrameArgs so that methods which use it are able to.
175 host_impl_
->WillBeginImplFrame(CreateBeginFrameArgsForTesting(
176 BEGINFRAME_FROM_HERE
,
177 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1)));
178 host_impl_
->DidFinishImplFrame();
182 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
183 root
->SetPosition(gfx::PointF());
184 root
->SetBounds(gfx::Size(10, 10));
185 root
->SetDrawsContent(true);
186 root
->draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
187 root
->SetHasRenderSurface(true);
188 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
191 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
192 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
193 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
194 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
197 static ::testing::AssertionResult
ScrollInfoContains(
198 const ScrollAndScaleSet
& scroll_info
,
200 const gfx::Vector2d
& scroll_delta
) {
201 int times_encountered
= 0;
203 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
204 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
207 if (scroll_delta
!= scroll_info
.scrolls
[i
].scroll_delta
) {
208 return ::testing::AssertionFailure()
209 << "Expected " << scroll_delta
.ToString() << ", not "
210 << scroll_info
.scrolls
[i
].scroll_delta
.ToString();
215 if (times_encountered
!= 1)
216 return ::testing::AssertionFailure() << "No layer found with id " << id
;
217 return ::testing::AssertionSuccess();
220 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
221 int times_encountered
= 0;
223 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
224 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
229 ASSERT_EQ(0, times_encountered
);
232 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
233 const gfx::Size
& content_size
) {
234 // Create both an inner viewport scroll layer and an outer viewport scroll
235 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
236 // 0x0, so the scrolls will be applied directly to the inner viewport.
237 const int kOuterViewportClipLayerId
= 116;
238 const int kOuterViewportScrollLayerId
= 117;
239 const int kContentLayerId
= 118;
240 const int kInnerViewportScrollLayerId
= 2;
241 const int kInnerViewportClipLayerId
= 4;
242 const int kPageScaleLayerId
= 5;
244 scoped_ptr
<LayerImpl
> root
=
245 LayerImpl::Create(layer_tree_impl
, 1);
246 root
->SetBounds(content_size
);
247 root
->SetPosition(gfx::PointF());
248 root
->SetHasRenderSurface(true);
250 scoped_ptr
<LayerImpl
> inner_scroll
=
251 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
252 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
253 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
255 scoped_ptr
<LayerImpl
> inner_clip
=
256 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
257 inner_clip
->SetBounds(
258 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
260 scoped_ptr
<LayerImpl
> page_scale
=
261 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
263 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
264 inner_scroll
->SetBounds(content_size
);
265 inner_scroll
->SetPosition(gfx::PointF());
267 scoped_ptr
<LayerImpl
> outer_clip
=
268 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
269 outer_clip
->SetBounds(content_size
);
270 outer_clip
->SetIsContainerForFixedPositionLayers(true);
272 scoped_ptr
<LayerImpl
> outer_scroll
=
273 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
274 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
275 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
276 outer_scroll
->SetBounds(content_size
);
277 outer_scroll
->SetPosition(gfx::PointF());
279 scoped_ptr
<LayerImpl
> contents
=
280 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
281 contents
->SetDrawsContent(true);
282 contents
->SetBounds(content_size
);
283 contents
->SetPosition(gfx::PointF());
285 outer_scroll
->AddChild(contents
.Pass());
286 outer_clip
->AddChild(outer_scroll
.Pass());
287 inner_scroll
->AddChild(outer_clip
.Pass());
288 page_scale
->AddChild(inner_scroll
.Pass());
289 inner_clip
->AddChild(page_scale
.Pass());
290 root
->AddChild(inner_clip
.Pass());
292 layer_tree_impl
->SetRootLayer(root
.Pass());
293 layer_tree_impl
->SetViewportLayersFromIds(
294 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
295 kOuterViewportScrollLayerId
);
297 layer_tree_impl
->DidBecomeActive();
298 return layer_tree_impl
->InnerViewportScrollLayer();
301 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
302 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
303 host_impl_
->active_tree(), content_size
);
304 host_impl_
->active_tree()->DidBecomeActive();
308 // Sets up a typical virtual viewport setup with one child content layer.
309 // Returns a pointer to the content layer.
310 LayerImpl
* CreateBasicVirtualViewportLayers(const gfx::Size
& viewport_size
,
311 const gfx::Size
& content_size
) {
312 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
313 // the inner a different size from the outer. We'll reuse its layer
314 // hierarchy but adjust the sizing to our needs.
315 CreateScrollAndContentsLayers(host_impl_
->active_tree(), content_size
);
317 LayerImpl
* content_layer
=
318 host_impl_
->OuterViewportScrollLayer()->children().back();
319 content_layer
->SetBounds(content_size
);
320 host_impl_
->OuterViewportScrollLayer()->SetBounds(content_size
);
322 LayerImpl
* outer_clip
= host_impl_
->OuterViewportScrollLayer()->parent();
323 outer_clip
->SetBounds(viewport_size
);
325 LayerImpl
* inner_clip_layer
=
326 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
327 inner_clip_layer
->SetBounds(viewport_size
);
328 host_impl_
->InnerViewportScrollLayer()->SetBounds(viewport_size
);
330 host_impl_
->SetViewportSize(viewport_size
);
331 host_impl_
->active_tree()->DidBecomeActive();
333 return content_layer
;
336 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
337 const gfx::Size
& size
,
338 LayerImpl
* clip_layer
) {
340 DCHECK(id
!= clip_layer
->id());
341 scoped_ptr
<LayerImpl
> layer
=
342 LayerImpl::Create(host_impl_
->active_tree(), id
);
343 layer
->SetScrollClipLayer(clip_layer
->id());
344 layer
->SetDrawsContent(true);
345 layer
->SetBounds(size
);
346 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
351 LayerTreeHostImpl::FrameData frame
;
352 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
353 host_impl_
->DrawLayers(&frame
);
354 host_impl_
->DidDrawAllLayers(frame
);
357 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
358 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
359 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
360 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
361 float device_scale_factor
);
363 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
364 // Note: It is not possible to disable the renderer once it has been set,
365 // so we do not need to test that disabling the renderer notifies us
366 // that can_draw changed.
367 EXPECT_FALSE(host_impl_
->CanDraw());
368 on_can_draw_state_changed_called_
= false;
370 // Set up the root layer, which allows us to draw.
371 SetupScrollAndContentsLayers(gfx::Size(100, 100));
372 EXPECT_TRUE(host_impl_
->CanDraw());
373 EXPECT_TRUE(on_can_draw_state_changed_called_
);
374 on_can_draw_state_changed_called_
= false;
376 // Toggle the root layer to make sure it toggles can_draw
377 host_impl_
->active_tree()->SetRootLayer(nullptr);
378 EXPECT_FALSE(host_impl_
->CanDraw());
379 EXPECT_TRUE(on_can_draw_state_changed_called_
);
380 on_can_draw_state_changed_called_
= false;
382 SetupScrollAndContentsLayers(gfx::Size(100, 100));
383 EXPECT_TRUE(host_impl_
->CanDraw());
384 EXPECT_TRUE(on_can_draw_state_changed_called_
);
385 on_can_draw_state_changed_called_
= false;
387 // Toggle the device viewport size to make sure it toggles can_draw.
388 host_impl_
->SetViewportSize(gfx::Size());
390 EXPECT_TRUE(host_impl_
->CanDraw());
392 EXPECT_FALSE(host_impl_
->CanDraw());
394 EXPECT_TRUE(on_can_draw_state_changed_called_
);
395 on_can_draw_state_changed_called_
= false;
397 host_impl_
->SetViewportSize(gfx::Size(100, 100));
398 EXPECT_TRUE(host_impl_
->CanDraw());
399 EXPECT_TRUE(on_can_draw_state_changed_called_
);
400 on_can_draw_state_changed_called_
= false;
403 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
406 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
407 return FakeOutputSurface::Create3d();
410 void DrawOneFrame() {
411 LayerTreeHostImpl::FrameData frame_data
;
412 host_impl_
->PrepareToDraw(&frame_data
);
413 host_impl_
->DidDrawAllLayers(frame_data
);
417 DebugScopedSetImplThread always_impl_thread_
;
418 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
420 TestSharedBitmapManager shared_bitmap_manager_
;
421 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
422 TestTaskGraphRunner task_graph_runner_
;
423 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
424 FakeRenderingStatsInstrumentation stats_instrumentation_
;
425 bool on_can_draw_state_changed_called_
;
426 bool did_notify_ready_to_activate_
;
427 bool did_request_commit_
;
428 bool did_request_redraw_
;
429 bool did_request_animate_
;
430 bool did_request_prepare_tiles_
;
431 bool did_complete_page_scale_animation_
;
432 bool reduce_memory_result_
;
433 base::Closure animation_task_
;
434 base::TimeDelta requested_animation_delay_
;
437 // A test fixture for new animation timelines tests.
438 class LayerTreeHostImplTimelinesTest
: public LayerTreeHostImplTest
{
440 void SetUp() override
{
441 LayerTreeSettings settings
= DefaultSettings();
442 settings
.use_compositor_animation_timelines
= true;
443 CreateHostImpl(settings
, CreateOutputSurface());
447 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
448 bool always_draw
= false;
449 CheckNotifyCalledIfCanDrawChanged(always_draw
);
452 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
453 CreateHostImpl(DefaultSettings(),
454 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
456 bool always_draw
= true;
457 CheckNotifyCalledIfCanDrawChanged(always_draw
);
460 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
461 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
463 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
464 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
467 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
469 scoped_ptr
<LayerImpl
> root
=
470 LayerImpl::Create(host_impl_
->active_tree(), 1);
471 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
472 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
473 root
->children()[1]->AddChild(
474 LayerImpl::Create(host_impl_
->active_tree(), 4));
475 root
->children()[1]->AddChild(
476 LayerImpl::Create(host_impl_
->active_tree(), 5));
477 root
->children()[1]->children()[0]->AddChild(
478 LayerImpl::Create(host_impl_
->active_tree(), 6));
479 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
481 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
483 ExpectClearedScrollDeltasRecursive(root
);
485 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
487 scroll_info
= host_impl_
->ProcessScrollDeltas();
488 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
489 ExpectClearedScrollDeltasRecursive(root
);
491 scroll_info
= host_impl_
->ProcessScrollDeltas();
492 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
493 ExpectClearedScrollDeltasRecursive(root
);
496 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
497 gfx::ScrollOffset
scroll_offset(20, 30);
498 gfx::Vector2d
scroll_delta(11, -15);
500 scoped_ptr
<LayerImpl
> root_clip
=
501 LayerImpl::Create(host_impl_
->active_tree(), 2);
502 scoped_ptr
<LayerImpl
> root
=
503 LayerImpl::Create(host_impl_
->active_tree(), 1);
504 root_clip
->SetBounds(gfx::Size(10, 10));
505 LayerImpl
* root_layer
= root
.get();
506 root_clip
->AddChild(root
.Pass());
507 root_layer
->SetBounds(gfx::Size(110, 110));
508 root_layer
->SetScrollClipLayer(root_clip
->id());
509 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
510 root_layer
->ScrollBy(scroll_delta
);
511 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
513 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
515 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
517 scroll_info
= host_impl_
->ProcessScrollDeltas();
518 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
519 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(), scroll_delta
));
521 gfx::Vector2d
scroll_delta2(-5, 27);
522 root
->ScrollBy(scroll_delta2
);
523 scroll_info
= host_impl_
->ProcessScrollDeltas();
524 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
525 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
526 scroll_delta
+ scroll_delta2
));
528 root
->ScrollBy(gfx::Vector2d());
529 scroll_info
= host_impl_
->ProcessScrollDeltas();
530 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
531 scroll_delta
+ scroll_delta2
));
534 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
535 SetupScrollAndContentsLayers(gfx::Size(100, 100));
536 host_impl_
->SetViewportSize(gfx::Size(50, 50));
539 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
540 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
541 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
542 InputHandler::WHEEL
));
543 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
544 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
545 InputHandler::WHEEL
));
546 host_impl_
->ScrollEnd();
547 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
548 InputHandler::WHEEL
));
549 EXPECT_TRUE(did_request_redraw_
);
550 EXPECT_TRUE(did_request_commit_
);
553 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
554 SetupScrollAndContentsLayers(gfx::Size(100, 100));
555 host_impl_
->SetViewportSize(gfx::Size(50, 50));
558 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
559 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
560 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
561 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
562 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
563 host_impl_
->ScrollEnd();
564 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
567 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
568 // We should not crash when trying to scroll an empty layer tree.
569 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
570 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
573 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
574 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
575 TestWebGraphicsContext3D::Create();
576 context_owned
->set_context_lost(true);
578 // Initialization will fail.
579 EXPECT_FALSE(CreateHostImpl(
580 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
582 SetupScrollAndContentsLayers(gfx::Size(100, 100));
584 // We should not crash when trying to scroll after the renderer initialization
586 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
587 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
590 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
591 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
592 host_impl_
->SetViewportSize(gfx::Size(50, 50));
595 // We should not crash if the tree is replaced while we are scrolling.
596 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
597 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
598 host_impl_
->active_tree()->DetachLayerTree();
600 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
602 // We should still be scrolling, because the scrolled layer also exists in the
604 gfx::Vector2d
scroll_delta(0, 10);
605 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
606 host_impl_
->ScrollEnd();
607 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
609 ScrollInfoContains(*scroll_info
, scroll_layer
->id(), scroll_delta
));
612 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
613 SetupScrollAndContentsLayers(gfx::Size(100, 100));
614 host_impl_
->SetViewportSize(gfx::Size(50, 50));
616 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
618 // With registered event handlers, wheel scrolls don't necessarily
619 // have to go to the main thread.
620 root
->SetHaveWheelEventHandlers(true);
621 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
622 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
623 host_impl_
->ScrollEnd();
625 // But typically the scroll-blocks-on mode will require them to.
626 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
627 SCROLL_BLOCKS_ON_START_TOUCH
);
628 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
629 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
631 // But gesture scrolls can still be handled.
632 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
633 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
634 host_impl_
->ScrollEnd();
636 // And if the handlers go away, wheel scrolls can again be processed
637 // on impl (despite the scroll-blocks-on mode).
638 root
->SetHaveWheelEventHandlers(false);
639 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
640 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
641 host_impl_
->ScrollEnd();
644 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
645 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
646 host_impl_
->SetViewportSize(gfx::Size(50, 50));
648 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
650 LayerImpl
* child
= 0;
652 scoped_ptr
<LayerImpl
> child_layer
=
653 LayerImpl::Create(host_impl_
->active_tree(), 6);
654 child
= child_layer
.get();
655 child_layer
->SetDrawsContent(true);
656 child_layer
->SetPosition(gfx::PointF(0, 20));
657 child_layer
->SetBounds(gfx::Size(50, 50));
658 scroll
->AddChild(child_layer
.Pass());
661 // Touch handler regions determine whether touch events block scroll.
662 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
663 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
664 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
665 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
666 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
668 // But they don't influence the actual handling of the scroll gestures.
669 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
670 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
671 host_impl_
->ScrollEnd();
673 // It's the union of scroll-blocks-on mode bits across all layers in the
674 // scroll paret chain that matters.
675 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
676 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
677 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
678 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
679 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
682 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
683 SetupScrollAndContentsLayers(gfx::Size(100, 100));
684 host_impl_
->SetViewportSize(gfx::Size(50, 50));
686 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
688 // With registered scroll handlers, scrolls don't generally have to go
689 // to the main thread.
690 root
->SetHaveScrollEventHandlers(true);
691 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
692 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
693 host_impl_
->ScrollEnd();
695 // Even the default scroll blocks on mode doesn't require this.
696 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
697 SCROLL_BLOCKS_ON_START_TOUCH
);
698 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
699 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
700 host_impl_
->ScrollEnd();
702 // But the page can opt in to blocking on scroll event handlers.
703 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
704 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
705 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
707 // GESTURE and WHEEL scrolls behave identically in this regard.
708 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
709 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
711 // And if the handlers go away, scrolls can again be processed on impl
712 // (despite the scroll-blocks-on mode).
713 root
->SetHaveScrollEventHandlers(false);
714 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
715 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
716 host_impl_
->ScrollEnd();
719 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
720 host_impl_
->SetViewportSize(gfx::Size(50, 50));
722 // Create a normal scrollable root layer
723 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
724 LayerImpl
* root_child
= root_scroll
->children()[0];
725 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
728 // Create two child scrollable layers
729 LayerImpl
* child1
= 0;
731 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
732 LayerImpl::Create(host_impl_
->active_tree(), 6);
733 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
734 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
735 child1
= scrollable_child_1
.get();
736 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
737 scrollable_child_1
->SetHaveWheelEventHandlers(true);
738 scrollable_child_1
->SetHaveScrollEventHandlers(true);
739 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
740 root_child
->AddChild(scrollable_child_clip_1
.Pass());
743 LayerImpl
* child2
= 0;
745 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
746 LayerImpl::Create(host_impl_
->active_tree(), 8);
747 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
748 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
749 child2
= scrollable_child_2
.get();
750 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
751 scrollable_child_2
->SetHaveWheelEventHandlers(true);
752 scrollable_child_2
->SetHaveScrollEventHandlers(true);
753 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
754 root_child
->AddChild(scrollable_child_clip_2
.Pass());
757 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
758 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
759 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
760 host_impl_
->ScrollEnd();
761 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
762 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
763 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
765 // But not those that hit only other layers.
766 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
767 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
768 host_impl_
->ScrollEnd();
770 // It's the union of bits set across the scroll ancestor chain that matters.
771 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
772 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
773 host_impl_
->ScrollEnd();
774 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
775 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
776 host_impl_
->ScrollEnd();
777 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
778 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
779 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
780 host_impl_
->ScrollEnd();
781 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
782 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
783 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
784 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
785 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
786 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
787 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
790 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
791 SetupScrollAndContentsLayers(gfx::Size(100, 100));
792 host_impl_
->SetViewportSize(gfx::Size(50, 50));
795 // Ignore the fling since no layer is being scrolled
796 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
798 // Start scrolling a layer
799 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
800 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
802 // Now the fling should go ahead since we've started scrolling a layer
803 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
806 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
807 SetupScrollAndContentsLayers(gfx::Size(100, 100));
808 host_impl_
->SetViewportSize(gfx::Size(50, 50));
811 // Ignore the fling since no layer is being scrolled
812 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
814 // Start scrolling a layer
815 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
816 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
818 // Now the fling should go ahead since we've started scrolling a layer
819 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
822 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
823 SetupScrollAndContentsLayers(gfx::Size(100, 100));
824 host_impl_
->SetViewportSize(gfx::Size(50, 50));
826 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
828 root
->SetShouldScrollOnMainThread(true);
830 // Start scrolling a layer
831 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
832 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
834 // The fling should be ignored since there's no layer being scrolled impl-side
835 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
838 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
839 SetupScrollAndContentsLayers(gfx::Size(100, 100));
840 host_impl_
->SetViewportSize(gfx::Size(50, 50));
842 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
844 root
->SetShouldScrollOnMainThread(true);
846 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
847 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
848 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
849 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
852 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
853 SetupScrollAndContentsLayers(gfx::Size(200, 200));
854 host_impl_
->SetViewportSize(gfx::Size(100, 100));
856 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
857 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
861 // All scroll types inside the non-fast scrollable region should fail.
862 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
863 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
864 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
865 InputHandler::WHEEL
));
866 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
867 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
868 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
869 InputHandler::GESTURE
));
871 // All scroll types outside this region should succeed.
872 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
873 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
874 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
875 InputHandler::GESTURE
));
876 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
877 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
878 InputHandler::GESTURE
));
879 host_impl_
->ScrollEnd();
880 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
881 InputHandler::GESTURE
));
882 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
883 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
884 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
885 InputHandler::GESTURE
));
886 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
887 host_impl_
->ScrollEnd();
888 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
889 InputHandler::GESTURE
));
892 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
893 SetupScrollAndContentsLayers(gfx::Size(200, 200));
894 host_impl_
->SetViewportSize(gfx::Size(100, 100));
896 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
897 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
898 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
902 // This point would fall into the non-fast scrollable region except that we've
903 // moved the layer down by 25 pixels.
904 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
905 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
906 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
907 InputHandler::WHEEL
));
908 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
909 host_impl_
->ScrollEnd();
911 // This point is still inside the non-fast region.
912 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
913 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
916 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
917 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
918 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
919 host_impl_
->SetViewportSize(gfx::Size(50, 50));
922 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
923 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
924 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
925 host_impl_
->ScrollEnd();
926 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
929 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
930 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
931 scroll_layer
->SetHaveScrollEventHandlers(true);
932 host_impl_
->SetViewportSize(gfx::Size(50, 50));
935 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
936 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
937 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
938 host_impl_
->ScrollEnd();
939 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
942 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
943 SetupScrollAndContentsLayers(gfx::Size(200, 200));
944 host_impl_
->SetViewportSize(gfx::Size(100, 100));
948 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
949 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
951 // Trying to scroll to the left/top will not succeed.
953 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
955 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
957 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
959 // Scrolling to the right/bottom will succeed.
961 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
963 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
965 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
967 // Scrolling to left/top will now succeed.
969 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
971 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
973 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
975 // Scrolling diagonally against an edge will succeed.
977 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
979 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
981 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
983 // Trying to scroll more than the available space will also succeed.
985 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
988 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
989 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
990 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
994 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
995 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
997 // Trying to scroll without a vertical scrollbar will fail.
998 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
999 gfx::Point(), SCROLL_FORWARD
));
1000 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
1001 gfx::Point(), SCROLL_BACKWARD
));
1003 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
1004 PaintedScrollbarLayerImpl::Create(
1005 host_impl_
->active_tree(),
1008 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1009 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1010 vertical_scrollbar
.get());
1012 // Trying to scroll with a vertical scrollbar will succeed.
1013 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1014 gfx::Point(), SCROLL_FORWARD
));
1015 EXPECT_FLOAT_EQ(875.f
,
1016 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1017 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1018 gfx::Point(), SCROLL_BACKWARD
));
1021 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1022 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1023 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1025 gfx::Size
overflow_size(400, 400);
1026 ASSERT_EQ(1u, scroll_layer
->children().size());
1027 LayerImpl
* overflow
= scroll_layer
->children()[0];
1028 overflow
->SetBounds(overflow_size
);
1029 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1030 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1031 overflow
->SetPosition(gfx::PointF());
1034 gfx::Point
scroll_position(10, 10);
1036 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1037 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1038 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1039 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1041 gfx::Vector2dF
scroll_delta(10, 10);
1042 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1043 host_impl_
->ScrollEnd();
1044 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1045 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1047 overflow
->set_user_scrollable_horizontal(false);
1049 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1050 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1052 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1054 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1055 host_impl_
->ScrollEnd();
1056 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1057 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1059 overflow
->set_user_scrollable_vertical(false);
1061 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1062 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1063 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1064 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1066 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1067 host_impl_
->ScrollEnd();
1068 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1069 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1072 TEST_F(LayerTreeHostImplTest
, AnimationSchedulingPendingTree
) {
1073 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1075 host_impl_
->CreatePendingTree();
1076 host_impl_
->pending_tree()->SetRootLayer(
1077 LayerImpl::Create(host_impl_
->pending_tree(), 1));
1078 LayerImpl
* root
= host_impl_
->pending_tree()->root_layer();
1079 root
->SetBounds(gfx::Size(50, 50));
1080 root
->SetHasRenderSurface(true);
1082 root
->AddChild(LayerImpl::Create(host_impl_
->pending_tree(), 2));
1083 LayerImpl
* child
= root
->children()[0];
1084 child
->SetBounds(gfx::Size(10, 10));
1085 child
->draw_properties().visible_layer_rect
= gfx::Rect(10, 10);
1086 child
->SetDrawsContent(true);
1087 AddAnimatedTransformToLayer(child
, 10.0, 3, 0);
1089 EXPECT_FALSE(did_request_animate_
);
1090 EXPECT_FALSE(did_request_redraw_
);
1091 EXPECT_FALSE(did_request_commit_
);
1093 host_impl_
->Animate();
1095 // An animation exists on the pending layer. Doing Animate() requests another
1097 // In reality, animations without has_set_start_time() == true do not need to
1098 // be continuously ticked on the pending tree, so it should not request
1099 // another animation frame here. But we currently do so blindly if any
1100 // animation exists.
1101 EXPECT_TRUE(did_request_animate_
);
1102 // The pending tree with an animation does not need to draw after animating.
1103 EXPECT_FALSE(did_request_redraw_
);
1104 EXPECT_FALSE(did_request_commit_
);
1106 did_request_animate_
= false;
1107 did_request_redraw_
= false;
1108 did_request_commit_
= false;
1110 host_impl_
->ActivateSyncTree();
1112 // When the animation activates, we should request another animation frame
1113 // to keep the animation moving.
1114 EXPECT_TRUE(did_request_animate_
);
1115 // On activation we don't need to request a redraw for the animation,
1116 // activating will draw on its own when it's ready.
1117 EXPECT_FALSE(did_request_redraw_
);
1118 EXPECT_FALSE(did_request_commit_
);
1121 TEST_F(LayerTreeHostImplTest
, AnimationSchedulingActiveTree
) {
1122 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1124 host_impl_
->active_tree()->SetRootLayer(
1125 LayerImpl::Create(host_impl_
->active_tree(), 1));
1126 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
1127 root
->SetBounds(gfx::Size(50, 50));
1128 root
->SetHasRenderSurface(true);
1130 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
1131 LayerImpl
* child
= root
->children()[0];
1132 child
->SetBounds(gfx::Size(10, 10));
1133 child
->draw_properties().visible_layer_rect
= gfx::Rect(10, 10);
1134 child
->SetDrawsContent(true);
1136 // Add a translate from 6,7 to 8,9.
1137 TransformOperations start
;
1138 start
.AppendTranslate(6.f
, 7.f
, 0.f
);
1139 TransformOperations end
;
1140 end
.AppendTranslate(8.f
, 9.f
, 0.f
);
1141 AddAnimatedTransformToLayer(child
, 4.0, start
, end
);
1143 base::TimeTicks now
= base::TimeTicks::Now();
1144 host_impl_
->WillBeginImplFrame(
1145 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now
));
1147 EXPECT_FALSE(did_request_animate_
);
1148 EXPECT_FALSE(did_request_redraw_
);
1149 EXPECT_FALSE(did_request_commit_
);
1151 host_impl_
->ActivateAnimations();
1152 did_request_animate_
= false;
1153 did_request_redraw_
= false;
1154 did_request_commit_
= false;
1156 host_impl_
->Animate();
1158 // An animation exists on the active layer. Doing Animate() requests another
1159 // frame after the current one.
1160 EXPECT_TRUE(did_request_animate_
);
1161 // TODO(danakj): We also need to draw in the current frame if something
1162 // animated, but this is currently handled by
1163 // SchedulerStateMachine::WillAnimate.
1164 EXPECT_FALSE(did_request_redraw_
);
1165 EXPECT_FALSE(did_request_commit_
);
1168 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1169 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1170 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1173 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1174 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1175 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1177 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1178 float page_scale_factor
= 1.f
;
1180 // The impl-based pinch zoom should adjust the max scroll position.
1182 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1183 page_scale_factor
, min_page_scale
, max_page_scale
);
1184 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1185 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1187 float page_scale_delta
= 2.f
;
1189 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1190 host_impl_
->PinchGestureBegin();
1191 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1192 host_impl_
->PinchGestureEnd();
1193 host_impl_
->ScrollEnd();
1194 EXPECT_FALSE(did_request_animate_
);
1195 EXPECT_TRUE(did_request_redraw_
);
1196 EXPECT_TRUE(did_request_commit_
);
1197 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1199 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1200 host_impl_
->ProcessScrollDeltas();
1201 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1203 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1204 scroll_layer
->MaxScrollOffset().ToString());
1207 // Scrolling after a pinch gesture should always be in local space. The
1208 // scroll deltas have the page scale factor applied.
1210 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1211 page_scale_factor
, min_page_scale
, max_page_scale
);
1212 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1213 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1215 float page_scale_delta
= 2.f
;
1216 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1217 host_impl_
->PinchGestureBegin();
1218 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1219 host_impl_
->PinchGestureEnd();
1220 host_impl_
->ScrollEnd();
1222 gfx::Vector2d
scroll_delta(0, 10);
1223 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1224 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1225 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1226 host_impl_
->ScrollEnd();
1228 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1229 host_impl_
->ProcessScrollDeltas();
1230 EXPECT_TRUE(ScrollInfoContains(
1231 *scroll_info
.get(), scroll_layer
->id(),
1232 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
)));
1236 TEST_F(LayerTreeHostImplTest
, ViewportScrollOrder
) {
1237 LayerTreeSettings settings
= DefaultSettings();
1238 settings
.invert_viewport_scroll_order
= true;
1239 CreateHostImpl(settings
,
1240 CreateOutputSurface());
1241 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.25f
, 4.f
);
1243 const gfx::Size
content_size(1000, 1000);
1244 const gfx::Size
viewport_size(500, 500);
1245 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1247 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1248 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1251 gfx::Vector2dF(500, 500),
1252 outer_scroll_layer
->MaxScrollOffset());
1254 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1255 host_impl_
->PinchGestureBegin();
1256 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1257 host_impl_
->PinchGestureEnd();
1258 host_impl_
->ScrollEnd();
1260 // Sanity check - we're zoomed in, starting from the origin.
1262 gfx::Vector2dF(0, 0),
1263 outer_scroll_layer
->CurrentScrollOffset());
1265 gfx::Vector2dF(0, 0),
1266 inner_scroll_layer
->CurrentScrollOffset());
1268 // Scroll down - only the inner viewport should scroll.
1269 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1270 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1271 host_impl_
->ScrollEnd();
1274 gfx::Vector2dF(50, 50),
1275 inner_scroll_layer
->CurrentScrollOffset());
1277 gfx::Vector2dF(0, 0),
1278 outer_scroll_layer
->CurrentScrollOffset());
1280 // Scroll down - outer viewport should start scrolling after the inner is at
1282 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1283 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f
, 1000.f
));
1284 host_impl_
->ScrollEnd();
1287 gfx::Vector2dF(250, 250),
1288 inner_scroll_layer
->CurrentScrollOffset());
1290 gfx::Vector2dF(300, 300),
1291 outer_scroll_layer
->CurrentScrollOffset());
1294 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1295 // as expected. That is, scrolling during a pinch should bubble from the inner
1296 // to the outer viewport.
1297 TEST_F(LayerTreeHostImplTest
, ScrollDuringPinchGesture
) {
1298 LayerTreeSettings settings
= DefaultSettings();
1299 settings
.invert_viewport_scroll_order
= true;
1300 CreateHostImpl(settings
,
1301 CreateOutputSurface());
1302 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1304 const gfx::Size
content_size(1000, 1000);
1305 const gfx::Size
viewport_size(500, 500);
1306 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1308 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1309 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1312 gfx::Vector2dF(500, 500),
1313 outer_scroll_layer
->MaxScrollOffset());
1315 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1316 host_impl_
->PinchGestureBegin();
1318 host_impl_
->PinchGestureUpdate(2, gfx::Point(250, 250));
1320 gfx::Vector2dF(0, 0),
1321 outer_scroll_layer
->CurrentScrollOffset());
1323 gfx::Vector2dF(125, 125),
1324 inner_scroll_layer
->CurrentScrollOffset());
1326 // Needed so that the pinch is accounted for in draw properties.
1329 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f
, 10.f
));
1331 gfx::Vector2dF(0, 0),
1332 outer_scroll_layer
->CurrentScrollOffset());
1334 gfx::Vector2dF(130, 130),
1335 inner_scroll_layer
->CurrentScrollOffset());
1339 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f
, 400.f
));
1341 gfx::Vector2dF(80, 80),
1342 outer_scroll_layer
->CurrentScrollOffset());
1344 gfx::Vector2dF(250, 250),
1345 inner_scroll_layer
->CurrentScrollOffset());
1347 host_impl_
->PinchGestureEnd();
1348 host_impl_
->ScrollEnd();
1351 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1352 // a pinch zoom is anchored within a certain margin of the screen edge, we
1353 // should assume the user means to scroll into the edge of the screen.
1354 TEST_F(LayerTreeHostImplTest
, PinchZoomSnapsToScreenEdge
) {
1355 LayerTreeSettings settings
= DefaultSettings();
1356 settings
.invert_viewport_scroll_order
= true;
1357 CreateHostImpl(settings
,
1358 CreateOutputSurface());
1359 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1361 const gfx::Size
content_size(1000, 1000);
1362 const gfx::Size
viewport_size(500, 500);
1363 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1365 int offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
- 5;
1366 gfx::Point
anchor(viewport_size
.width() - offsetFromEdge
,
1367 viewport_size
.height() - offsetFromEdge
);
1369 // Pinch in within the margins. The scroll should stay exactly locked to the
1370 // bottom and right.
1371 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1372 host_impl_
->PinchGestureBegin();
1373 host_impl_
->PinchGestureUpdate(2, anchor
);
1374 host_impl_
->PinchGestureEnd();
1375 host_impl_
->ScrollEnd();
1378 gfx::Vector2dF(250, 250),
1379 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1382 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1383 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1384 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1386 // Pinch in within the margins. The scroll should stay exactly locked to the
1388 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1389 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1390 host_impl_
->PinchGestureBegin();
1391 host_impl_
->PinchGestureUpdate(2, anchor
);
1392 host_impl_
->PinchGestureEnd();
1393 host_impl_
->ScrollEnd();
1396 gfx::Vector2dF(0, 0),
1397 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1400 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1401 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1402 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1404 // Pinch in just outside the margin. There should be no snapping.
1405 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1406 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1407 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1408 host_impl_
->PinchGestureBegin();
1409 host_impl_
->PinchGestureUpdate(2, anchor
);
1410 host_impl_
->PinchGestureEnd();
1411 host_impl_
->ScrollEnd();
1414 gfx::Vector2dF(50, 50),
1415 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1418 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1419 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1420 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1422 // Pinch in just outside the margin. There should be no snapping.
1423 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1424 anchor
= gfx::Point(viewport_size
.width() - offsetFromEdge
,
1425 viewport_size
.height() - offsetFromEdge
);
1426 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1427 host_impl_
->PinchGestureBegin();
1428 host_impl_
->PinchGestureUpdate(2, anchor
);
1429 host_impl_
->PinchGestureEnd();
1430 host_impl_
->ScrollEnd();
1433 gfx::Vector2dF(200, 200),
1434 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1437 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1438 const gfx::Size
content_size(200, 200);
1439 const gfx::Size
viewport_size(100, 100);
1440 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1442 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1443 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1445 // Zoom into the page by a 2X factor
1446 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1447 float page_scale_factor
= 2.f
;
1448 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1449 page_scale_factor
, min_page_scale
, max_page_scale
);
1450 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1452 // Scroll by a small amount, there should be no bubbling up to the inner
1454 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1455 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1456 host_impl_
->ScrollEnd();
1459 gfx::Vector2dF(5, 10),
1460 outer_scroll_layer
->CurrentScrollOffset());
1463 inner_scroll_layer
->CurrentScrollOffset());
1465 // Scroll by the outer viewport's max scroll extent, there the remainder
1466 // should bubble up to the inner viewport.
1467 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1468 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f
, 200.f
));
1469 host_impl_
->ScrollEnd();
1472 gfx::Vector2dF(100, 100),
1473 outer_scroll_layer
->CurrentScrollOffset());
1475 gfx::Vector2dF(5, 10),
1476 inner_scroll_layer
->CurrentScrollOffset());
1478 // Scroll by the inner viewport's max scroll extent, it should all go to the
1480 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1481 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f
, 80.f
));
1482 host_impl_
->ScrollEnd();
1485 gfx::Vector2dF(100, 100),
1486 outer_scroll_layer
->CurrentScrollOffset());
1488 gfx::Vector2dF(50, 50),
1489 inner_scroll_layer
->CurrentScrollOffset());
1492 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1493 ui::LatencyInfo latency_info
;
1494 latency_info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0,
1496 scoped_ptr
<SwapPromise
> swap_promise(
1497 new LatencyInfoSwapPromise(latency_info
));
1499 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1500 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1501 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1502 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1503 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1504 host_impl_
->ScrollEnd();
1506 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1507 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1508 EXPECT_EQ(latency_info
.trace_id(), scroll_info
->swap_promises
[0]->TraceId());
1511 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1512 // up to the scroll_parent, rather than the stacking parent.
1513 TEST_F(LayerTreeHostImplTest
, ScrollBubblesToScrollParent
) {
1514 LayerImpl
* viewport_scroll
=
1515 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1516 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1518 // Set up two scrolling children of the root, one of which is a scroll parent
1519 // to the other. Scrolls bubbling from the child should bubble to the parent,
1520 // not the viewport.
1523 LayerImpl
*child_clip
;
1525 scoped_ptr
<LayerImpl
> scroll_parent_clip
=
1526 LayerImpl::Create(host_impl_
->active_tree(), 6);
1527 scoped_ptr
<LayerImpl
> scroll_parent
= CreateScrollableLayer(
1528 7, gfx::Size(10, 10), scroll_parent_clip
.get());
1529 parent
= scroll_parent
.get();
1530 scroll_parent_clip
->AddChild(scroll_parent
.Pass());
1532 viewport_scroll
->AddChild(scroll_parent_clip
.Pass());
1534 scoped_ptr
<LayerImpl
> scroll_child_clip
=
1535 LayerImpl::Create(host_impl_
->active_tree(), 8);
1536 scoped_ptr
<LayerImpl
> scroll_child
= CreateScrollableLayer(
1537 9, gfx::Size(10, 10), scroll_child_clip
.get());
1538 child
= scroll_child
.get();
1539 scroll_child
->SetPosition(gfx::Point(20, 20));
1540 scroll_child_clip
->AddChild(scroll_child
.Pass());
1542 child_clip
= scroll_child_clip
.get();
1543 viewport_scroll
->AddChild(scroll_child_clip
.Pass());
1545 child_clip
->SetScrollParent(parent
);
1550 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1551 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1552 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1553 host_impl_
->ScrollEnd();
1555 // The child should be fully scrolled by the first ScrollBy.
1556 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child
->CurrentScrollOffset());
1558 // The scroll_parent should receive the bubbled up second ScrollBy.
1559 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent
->CurrentScrollOffset());
1561 // The viewport shouldn't have been scrolled at all.
1563 gfx::Vector2dF(0, 0),
1564 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1566 gfx::Vector2dF(0, 0),
1567 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1571 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1572 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1573 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1574 host_impl_
->ScrollEnd();
1576 // The first ScrollBy should scroll the parent to its extent.
1577 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent
->CurrentScrollOffset());
1579 // The viewport should now be next in bubbling order.
1581 gfx::Vector2dF(2, 1),
1582 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1584 gfx::Vector2dF(0, 0),
1585 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1590 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1591 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1592 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1595 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1596 DCHECK(scroll_layer
);
1598 float min_page_scale
= 1.f
;
1599 float max_page_scale
= 4.f
;
1601 // Basic pinch zoom in gesture
1603 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1605 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1607 float page_scale_delta
= 2.f
;
1608 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1609 host_impl_
->PinchGestureBegin();
1610 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1611 host_impl_
->PinchGestureEnd();
1612 host_impl_
->ScrollEnd();
1613 EXPECT_FALSE(did_request_animate_
);
1614 EXPECT_TRUE(did_request_redraw_
);
1615 EXPECT_TRUE(did_request_commit_
);
1617 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1618 host_impl_
->ProcessScrollDeltas();
1619 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1624 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1626 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1627 float page_scale_delta
= 10.f
;
1629 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1630 host_impl_
->PinchGestureBegin();
1631 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1632 host_impl_
->PinchGestureEnd();
1633 host_impl_
->ScrollEnd();
1635 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1636 host_impl_
->ProcessScrollDeltas();
1637 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1640 // Zoom-out clamping
1642 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1644 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1645 scroll_layer
->PullDeltaForMainThread();
1646 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1648 float page_scale_delta
= 0.1f
;
1649 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1650 host_impl_
->PinchGestureBegin();
1651 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1652 host_impl_
->PinchGestureEnd();
1653 host_impl_
->ScrollEnd();
1655 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1656 host_impl_
->ProcessScrollDeltas();
1657 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1659 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1662 // Two-finger panning should not happen based on pinch events only
1664 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1666 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1667 scroll_layer
->PullDeltaForMainThread();
1668 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1670 float page_scale_delta
= 1.f
;
1671 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1672 host_impl_
->PinchGestureBegin();
1673 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1674 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1675 host_impl_
->PinchGestureEnd();
1676 host_impl_
->ScrollEnd();
1678 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1679 host_impl_
->ProcessScrollDeltas();
1680 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1681 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1684 // Two-finger panning should work with interleaved scroll events
1686 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1688 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1689 scroll_layer
->PullDeltaForMainThread();
1690 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1692 float page_scale_delta
= 1.f
;
1693 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1694 host_impl_
->PinchGestureBegin();
1695 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1696 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1697 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1698 host_impl_
->PinchGestureEnd();
1699 host_impl_
->ScrollEnd();
1701 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1702 host_impl_
->ProcessScrollDeltas();
1703 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1704 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1705 gfx::Vector2d(-10, -10)));
1708 // Two-finger panning should work when starting fully zoomed out.
1710 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1711 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1712 scroll_layer
->PullDeltaForMainThread();
1713 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1715 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1716 host_impl_
->PinchGestureBegin();
1717 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1718 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1719 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1720 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1721 host_impl_
->PinchGestureEnd();
1722 host_impl_
->ScrollEnd();
1724 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1725 host_impl_
->ProcessScrollDeltas();
1726 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1727 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1728 gfx::Vector2d(20, 20)));
1732 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1733 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1734 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1737 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1738 DCHECK(scroll_layer
);
1740 float min_page_scale
= 0.5f
;
1741 float max_page_scale
= 4.f
;
1742 base::TimeTicks start_time
= base::TimeTicks() +
1743 base::TimeDelta::FromSeconds(1);
1744 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1745 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1746 base::TimeTicks end_time
= start_time
+ duration
;
1748 BeginFrameArgs begin_frame_args
=
1749 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1751 // Non-anchor zoom-in
1753 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1755 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1757 did_request_redraw_
= false;
1758 did_request_animate_
= false;
1759 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1760 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1765 host_impl_
->ActivateSyncTree();
1766 EXPECT_FALSE(did_request_redraw_
);
1767 EXPECT_TRUE(did_request_animate_
);
1769 did_request_redraw_
= false;
1770 did_request_animate_
= false;
1771 begin_frame_args
.frame_time
= start_time
;
1772 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1773 host_impl_
->Animate();
1774 EXPECT_TRUE(did_request_redraw_
);
1775 EXPECT_TRUE(did_request_animate_
);
1776 host_impl_
->DidFinishImplFrame();
1778 did_request_redraw_
= false;
1779 did_request_animate_
= false;
1780 begin_frame_args
.frame_time
= halfway_through_animation
;
1781 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1782 host_impl_
->Animate();
1783 EXPECT_TRUE(did_request_redraw_
);
1784 EXPECT_TRUE(did_request_animate_
);
1785 host_impl_
->DidFinishImplFrame();
1787 did_request_redraw_
= false;
1788 did_request_animate_
= false;
1789 did_request_commit_
= false;
1790 begin_frame_args
.frame_time
= end_time
;
1791 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1792 host_impl_
->Animate();
1793 EXPECT_TRUE(did_request_commit_
);
1794 EXPECT_FALSE(did_request_animate_
);
1795 host_impl_
->DidFinishImplFrame();
1797 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1798 host_impl_
->ProcessScrollDeltas();
1799 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1800 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1801 gfx::Vector2d(-50, -50)));
1804 start_time
+= base::TimeDelta::FromSeconds(10);
1805 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1806 end_time
+= base::TimeDelta::FromSeconds(10);
1810 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1812 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1814 did_request_redraw_
= false;
1815 did_request_animate_
= false;
1816 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1817 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1818 gfx::Vector2d(25, 25),
1822 host_impl_
->ActivateSyncTree();
1823 EXPECT_FALSE(did_request_redraw_
);
1824 EXPECT_TRUE(did_request_animate_
);
1826 did_request_redraw_
= false;
1827 did_request_animate_
= false;
1828 begin_frame_args
.frame_time
= start_time
;
1829 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1830 host_impl_
->Animate();
1831 EXPECT_TRUE(did_request_redraw_
);
1832 EXPECT_TRUE(did_request_animate_
);
1833 host_impl_
->DidFinishImplFrame();
1835 did_request_redraw_
= false;
1836 did_request_commit_
= false;
1837 did_request_animate_
= false;
1838 begin_frame_args
.frame_time
= end_time
;
1839 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1840 host_impl_
->Animate();
1841 EXPECT_TRUE(did_request_redraw_
);
1842 EXPECT_FALSE(did_request_animate_
);
1843 EXPECT_TRUE(did_request_commit_
);
1844 host_impl_
->DidFinishImplFrame();
1846 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1847 host_impl_
->ProcessScrollDeltas();
1848 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1849 // Pushed to (0,0) via clamping against contents layer size.
1850 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1851 gfx::Vector2d(-50, -50)));
1855 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1856 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1857 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1860 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1861 DCHECK(scroll_layer
);
1863 float min_page_scale
= 0.5f
;
1864 float max_page_scale
= 4.f
;
1865 base::TimeTicks start_time
= base::TimeTicks() +
1866 base::TimeDelta::FromSeconds(1);
1867 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1868 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1869 base::TimeTicks end_time
= start_time
+ duration
;
1871 BeginFrameArgs begin_frame_args
=
1872 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1874 // Anchor zoom with unchanged page scale should not change scroll or scale.
1876 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1878 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1880 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1881 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1886 host_impl_
->ActivateSyncTree();
1887 begin_frame_args
.frame_time
= start_time
;
1888 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1889 host_impl_
->Animate();
1890 host_impl_
->DidFinishImplFrame();
1892 begin_frame_args
.frame_time
= halfway_through_animation
;
1893 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1894 host_impl_
->Animate();
1895 EXPECT_TRUE(did_request_redraw_
);
1896 host_impl_
->DidFinishImplFrame();
1898 begin_frame_args
.frame_time
= end_time
;
1899 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1900 host_impl_
->Animate();
1901 EXPECT_TRUE(did_request_commit_
);
1902 host_impl_
->DidFinishImplFrame();
1904 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1905 host_impl_
->ProcessScrollDeltas();
1906 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1907 ExpectNone(*scroll_info
, scroll_layer
->id());
1911 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1912 host_impl_
->CreatePendingTree();
1913 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
1914 CreateScrollAndContentsLayers(
1915 host_impl_
->pending_tree(),
1916 gfx::Size(100, 100));
1917 host_impl_
->ActivateSyncTree();
1920 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1921 DCHECK(scroll_layer
);
1923 float min_page_scale
= 0.5f
;
1924 float max_page_scale
= 4.f
;
1925 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1927 host_impl_
->ActivateSyncTree();
1929 base::TimeTicks start_time
= base::TimeTicks() +
1930 base::TimeDelta::FromSeconds(1);
1931 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1932 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1933 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1934 base::TimeTicks end_time
= start_time
+ duration
;
1935 float target_scale
= 2.f
;
1937 BeginFrameArgs begin_frame_args
=
1938 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1940 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1942 // Make sure TakePageScaleAnimation works properly.
1944 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1945 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1950 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1951 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1952 EXPECT_EQ(target_scale
, psa
->scale
);
1953 EXPECT_EQ(duration
, psa
->duration
);
1954 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1956 // Recreate the PSA. Nothing should happen here since the tree containing the
1957 // PSA hasn't been activated yet.
1958 did_request_redraw_
= false;
1959 did_request_animate_
= false;
1960 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1961 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1966 begin_frame_args
.frame_time
= halfway_through_animation
;
1967 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1968 host_impl_
->Animate();
1969 EXPECT_FALSE(did_request_animate_
);
1970 EXPECT_FALSE(did_request_redraw_
);
1971 host_impl_
->DidFinishImplFrame();
1973 // Activate the sync tree. This should cause the animation to become enabled.
1974 // It should also clear the pointer on the sync tree.
1975 host_impl_
->ActivateSyncTree();
1977 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1978 EXPECT_FALSE(did_request_redraw_
);
1979 EXPECT_TRUE(did_request_animate_
);
1981 start_time
+= base::TimeDelta::FromSeconds(10);
1982 third_through_animation
+= base::TimeDelta::FromSeconds(10);
1983 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1984 end_time
+= base::TimeDelta::FromSeconds(10);
1986 // From here on, make sure the animation runs as normal.
1987 did_request_redraw_
= false;
1988 did_request_animate_
= false;
1989 begin_frame_args
.frame_time
= start_time
;
1990 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1991 host_impl_
->Animate();
1992 EXPECT_TRUE(did_request_redraw_
);
1993 EXPECT_TRUE(did_request_animate_
);
1994 host_impl_
->DidFinishImplFrame();
1996 did_request_redraw_
= false;
1997 did_request_animate_
= false;
1998 begin_frame_args
.frame_time
= third_through_animation
;
1999 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2000 host_impl_
->Animate();
2001 EXPECT_TRUE(did_request_redraw_
);
2002 EXPECT_TRUE(did_request_animate_
);
2003 host_impl_
->DidFinishImplFrame();
2005 // Another activation shouldn't have any effect on the animation.
2006 host_impl_
->ActivateSyncTree();
2008 did_request_redraw_
= false;
2009 did_request_animate_
= false;
2010 begin_frame_args
.frame_time
= halfway_through_animation
;
2011 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2012 host_impl_
->Animate();
2013 EXPECT_TRUE(did_request_redraw_
);
2014 EXPECT_TRUE(did_request_animate_
);
2015 host_impl_
->DidFinishImplFrame();
2017 did_request_redraw_
= false;
2018 did_request_animate_
= false;
2019 did_request_commit_
= false;
2020 begin_frame_args
.frame_time
= end_time
;
2021 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2022 host_impl_
->Animate();
2023 EXPECT_TRUE(did_request_commit_
);
2024 EXPECT_FALSE(did_request_animate_
);
2025 host_impl_
->DidFinishImplFrame();
2027 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
2028 host_impl_
->ProcessScrollDeltas();
2029 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
2030 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
2031 gfx::Vector2d(-50, -50)));
2034 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
2035 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2036 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2039 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
2040 DCHECK(scroll_layer
);
2042 base::TimeTicks start_time
=
2043 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
2044 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
2045 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
2046 base::TimeTicks end_time
= start_time
+ duration
;
2048 BeginFrameArgs begin_frame_args
=
2049 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
2051 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2052 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
2054 did_complete_page_scale_animation_
= false;
2055 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
2056 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
2057 gfx::Vector2d(), false, 2.f
, duration
)));
2058 host_impl_
->ActivateSyncTree();
2059 begin_frame_args
.frame_time
= start_time
;
2060 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2061 host_impl_
->Animate();
2062 EXPECT_FALSE(did_complete_page_scale_animation_
);
2063 host_impl_
->DidFinishImplFrame();
2065 begin_frame_args
.frame_time
= halfway_through_animation
;
2066 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2067 host_impl_
->Animate();
2068 EXPECT_FALSE(did_complete_page_scale_animation_
);
2069 host_impl_
->DidFinishImplFrame();
2071 begin_frame_args
.frame_time
= end_time
;
2072 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2073 host_impl_
->Animate();
2074 EXPECT_TRUE(did_complete_page_scale_animation_
);
2075 host_impl_
->DidFinishImplFrame();
2078 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
2080 LayerTreeHostImplOverridePhysicalTime(
2081 const LayerTreeSettings
& settings
,
2082 LayerTreeHostImplClient
* client
,
2084 SharedBitmapManager
* manager
,
2085 TaskGraphRunner
* task_graph_runner
,
2086 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
2087 : LayerTreeHostImpl(settings
,
2090 rendering_stats_instrumentation
,
2096 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
2097 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
2098 fake_current_physical_time_
);
2101 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
2102 fake_current_physical_time_
= fake_now
;
2106 base::TimeTicks fake_current_physical_time_
;
2109 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
2111 void SetupLayers(LayerTreeSettings settings
) {
2112 gfx::Size
content_size(100, 100);
2114 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
2115 new LayerTreeHostImplOverridePhysicalTime(
2116 settings
, this, &proxy_
, &shared_bitmap_manager_
,
2117 &task_graph_runner_
, &stats_instrumentation_
);
2118 host_impl_
= make_scoped_ptr(host_impl_override_time
);
2119 host_impl_
->InitializeRenderer(CreateOutputSurface());
2121 SetupScrollAndContentsLayers(content_size
);
2122 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2123 host_impl_
->SetViewportSize(
2124 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
2126 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
2127 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 400,
2128 VERTICAL
, 10, 0, false, true);
2129 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
2131 LayerImpl
* scroll
= host_impl_
->InnerViewportScrollLayer();
2132 LayerImpl
* root
= scroll
->parent()->parent();
2133 scrollbar
->SetScrollLayerAndClipLayerByIds(scroll
->id(), root
->id());
2134 root
->AddChild(scrollbar
.Pass());
2136 host_impl_
->active_tree()->DidBecomeActive();
2140 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
2141 LayerTreeSettings settings
;
2142 settings
.scrollbar_animator
= animator
;
2143 settings
.scrollbar_fade_delay_ms
= 20;
2144 settings
.scrollbar_fade_duration_ms
= 20;
2146 SetupLayers(settings
);
2148 base::TimeTicks fake_now
= base::TimeTicks::Now();
2150 EXPECT_FALSE(did_request_animate_
);
2151 EXPECT_FALSE(did_request_redraw_
);
2152 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2153 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2155 // If no scroll happened during a scroll gesture, it should have no effect.
2156 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2157 host_impl_
->ScrollEnd();
2158 EXPECT_FALSE(did_request_animate_
);
2159 EXPECT_FALSE(did_request_redraw_
);
2160 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2161 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2163 // After a scroll, a scrollbar animation should be scheduled about 20ms from
2165 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2166 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2167 EXPECT_FALSE(did_request_animate_
);
2168 EXPECT_TRUE(did_request_redraw_
);
2169 did_request_redraw_
= false;
2170 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2171 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2173 host_impl_
->ScrollEnd();
2174 EXPECT_FALSE(did_request_animate_
);
2175 EXPECT_FALSE(did_request_redraw_
);
2176 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2177 requested_animation_delay_
);
2178 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2180 fake_now
+= requested_animation_delay_
;
2181 requested_animation_delay_
= base::TimeDelta();
2182 animation_task_
.Run();
2183 animation_task_
= base::Closure();
2184 EXPECT_TRUE(did_request_animate_
);
2185 did_request_animate_
= false;
2186 EXPECT_FALSE(did_request_redraw_
);
2188 // After the scrollbar animation begins, we should start getting redraws.
2189 BeginFrameArgs begin_frame_args
=
2190 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, fake_now
);
2191 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2192 host_impl_
->Animate();
2193 EXPECT_TRUE(did_request_animate_
);
2194 did_request_animate_
= false;
2195 EXPECT_TRUE(did_request_redraw_
);
2196 did_request_redraw_
= false;
2197 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2198 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2199 host_impl_
->DidFinishImplFrame();
2201 // Setting the scroll offset outside a scroll should also cause the
2202 // scrollbar to appear and to schedule a scrollbar animation.
2203 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2204 gfx::ScrollOffset(5, 5));
2205 EXPECT_FALSE(did_request_animate_
);
2206 EXPECT_FALSE(did_request_redraw_
);
2207 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2208 requested_animation_delay_
);
2209 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2210 requested_animation_delay_
= base::TimeDelta();
2211 animation_task_
= base::Closure();
2213 // Scrollbar animation is not triggered unnecessarily.
2214 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2215 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2216 EXPECT_FALSE(did_request_animate_
);
2217 EXPECT_TRUE(did_request_redraw_
);
2218 did_request_redraw_
= false;
2219 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2220 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2222 host_impl_
->ScrollEnd();
2223 EXPECT_FALSE(did_request_animate_
);
2224 EXPECT_FALSE(did_request_redraw_
);
2225 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2226 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2228 // Changing page scale triggers scrollbar animation.
2229 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2230 host_impl_
->SetPageScaleOnActiveTree(1.1f
);
2231 EXPECT_FALSE(did_request_animate_
);
2232 EXPECT_FALSE(did_request_redraw_
);
2233 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2234 requested_animation_delay_
);
2235 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2236 requested_animation_delay_
= base::TimeDelta();
2237 animation_task_
= base::Closure();
2241 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
2242 RunTest(LayerTreeSettings::LINEAR_FADE
);
2245 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
2246 RunTest(LayerTreeSettings::THINNING
);
2249 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2250 float device_scale_factor
) {
2251 LayerTreeSettings settings
;
2252 settings
.scrollbar_fade_delay_ms
= 500;
2253 settings
.scrollbar_fade_duration_ms
= 300;
2254 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
2256 gfx::Size
viewport_size(300, 200);
2257 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
2258 gfx::ScaleSize(viewport_size
, device_scale_factor
));
2259 gfx::Size
content_size(1000, 1000);
2261 CreateHostImpl(settings
, CreateOutputSurface());
2262 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
2263 host_impl_
->SetViewportSize(device_viewport_size
);
2265 scoped_ptr
<LayerImpl
> root
=
2266 LayerImpl::Create(host_impl_
->active_tree(), 1);
2267 root
->SetBounds(viewport_size
);
2268 root
->SetHasRenderSurface(true);
2270 scoped_ptr
<LayerImpl
> scroll
=
2271 LayerImpl::Create(host_impl_
->active_tree(), 2);
2272 scroll
->SetScrollClipLayer(root
->id());
2273 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2274 scroll
->SetBounds(content_size
);
2275 scroll
->SetIsContainerForFixedPositionLayers(true);
2277 scoped_ptr
<LayerImpl
> contents
=
2278 LayerImpl::Create(host_impl_
->active_tree(), 3);
2279 contents
->SetDrawsContent(true);
2280 contents
->SetBounds(content_size
);
2282 // The scrollbar is on the right side.
2283 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
2284 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
2285 scrollbar
->SetDrawsContent(true);
2286 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
2287 scrollbar
->SetPosition(gfx::Point(285, 0));
2289 scroll
->AddChild(contents
.Pass());
2290 root
->AddChild(scroll
.Pass());
2291 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
2292 root
->AddChild(scrollbar
.Pass());
2294 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2295 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
2297 host_impl_
->active_tree()->DidBecomeActive();
2300 LayerImpl
* root_scroll
=
2301 host_impl_
->active_tree()->InnerViewportScrollLayer();
2302 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
2303 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
2304 static_cast<ScrollbarAnimationControllerThinning
*>(
2305 root_scroll
->scrollbar_animation_controller());
2306 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
2308 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
2309 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2311 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
2312 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2314 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2315 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2317 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
2318 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2319 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2321 did_request_redraw_
= false;
2322 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2323 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
2324 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2325 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
2326 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2327 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
2328 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2331 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
2332 SetupMouseMoveAtWithDeviceScale(1.f
);
2335 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
2336 SetupMouseMoveAtWithDeviceScale(2.f
);
2339 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
2340 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2341 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2342 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2345 CompositorFrameMetadata metadata
=
2346 host_impl_
->MakeCompositorFrameMetadata();
2347 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
2348 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
2349 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
2350 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2351 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2352 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2353 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2354 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2357 // Scrolling should update metadata immediately.
2358 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2359 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2360 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2362 CompositorFrameMetadata metadata
=
2363 host_impl_
->MakeCompositorFrameMetadata();
2364 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2366 host_impl_
->ScrollEnd();
2368 CompositorFrameMetadata metadata
=
2369 host_impl_
->MakeCompositorFrameMetadata();
2370 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2373 // Root "overflow: hidden" properties should be reflected on the outer
2374 // viewport scroll layer.
2376 host_impl_
->active_tree()
2377 ->OuterViewportScrollLayer()
2378 ->set_user_scrollable_horizontal(false);
2379 CompositorFrameMetadata metadata
=
2380 host_impl_
->MakeCompositorFrameMetadata();
2381 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2382 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2384 host_impl_
->active_tree()
2385 ->OuterViewportScrollLayer()
2386 ->set_user_scrollable_vertical(false);
2387 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2388 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2389 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2392 // Re-enable scrollability and verify that overflows are no longer hidden.
2394 host_impl_
->active_tree()
2395 ->OuterViewportScrollLayer()
2396 ->set_user_scrollable_horizontal(true);
2397 host_impl_
->active_tree()
2398 ->OuterViewportScrollLayer()
2399 ->set_user_scrollable_vertical(true);
2400 CompositorFrameMetadata metadata
=
2401 host_impl_
->MakeCompositorFrameMetadata();
2402 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2403 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2406 // Root "overflow: hidden" properties should also be reflected on the
2407 // inner viewport scroll layer.
2409 host_impl_
->active_tree()
2410 ->InnerViewportScrollLayer()
2411 ->set_user_scrollable_horizontal(false);
2412 CompositorFrameMetadata metadata
=
2413 host_impl_
->MakeCompositorFrameMetadata();
2414 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2415 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2417 host_impl_
->active_tree()
2418 ->InnerViewportScrollLayer()
2419 ->set_user_scrollable_vertical(false);
2420 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2421 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2422 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2425 // Page scale should update metadata correctly (shrinking only the viewport).
2426 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
2427 host_impl_
->PinchGestureBegin();
2428 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
2429 host_impl_
->PinchGestureEnd();
2430 host_impl_
->ScrollEnd();
2432 CompositorFrameMetadata metadata
=
2433 host_impl_
->MakeCompositorFrameMetadata();
2434 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2435 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
2436 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
2437 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2438 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2439 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2442 // Likewise if set from the main thread.
2443 host_impl_
->ProcessScrollDeltas();
2444 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
2445 host_impl_
->SetPageScaleOnActiveTree(4.f
);
2447 CompositorFrameMetadata metadata
=
2448 host_impl_
->MakeCompositorFrameMetadata();
2449 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2450 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
2451 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
2452 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2453 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2454 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2458 class DidDrawCheckLayer
: public LayerImpl
{
2460 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2461 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2464 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2465 will_draw_called_
= true;
2466 if (will_draw_returns_false_
)
2468 return LayerImpl::WillDraw(draw_mode
, provider
);
2471 void AppendQuads(RenderPass
* render_pass
,
2472 AppendQuadsData
* append_quads_data
) override
{
2473 append_quads_called_
= true;
2474 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2477 void DidDraw(ResourceProvider
* provider
) override
{
2478 did_draw_called_
= true;
2479 LayerImpl::DidDraw(provider
);
2482 bool will_draw_called() const { return will_draw_called_
; }
2483 bool append_quads_called() const { return append_quads_called_
; }
2484 bool did_draw_called() const { return did_draw_called_
; }
2486 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2488 void ClearDidDrawCheck() {
2489 will_draw_called_
= false;
2490 append_quads_called_
= false;
2491 did_draw_called_
= false;
2494 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2496 void AddCopyRequest() {
2497 ScopedPtrVector
<CopyOutputRequest
> requests
;
2499 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2500 SetHasRenderSurface(true);
2501 PassCopyRequests(&requests
);
2505 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2506 : LayerImpl(tree_impl
, id
),
2507 will_draw_returns_false_(false),
2508 will_draw_called_(false),
2509 append_quads_called_(false),
2510 did_draw_called_(false) {
2511 SetBounds(gfx::Size(10, 10));
2512 SetDrawsContent(true);
2513 draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
2517 bool will_draw_returns_false_
;
2518 bool will_draw_called_
;
2519 bool append_quads_called_
;
2520 bool did_draw_called_
;
2523 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2524 // The root layer is always drawn, so run this test on a child layer that
2525 // will be masked out by the root layer's bounds.
2526 host_impl_
->active_tree()->SetRootLayer(
2527 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2528 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2529 host_impl_
->active_tree()->root_layer());
2531 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2532 root
->SetHasRenderSurface(true);
2533 DidDrawCheckLayer
* layer
=
2534 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2537 LayerTreeHostImpl::FrameData frame
;
2538 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2539 host_impl_
->DrawLayers(&frame
);
2540 host_impl_
->DidDrawAllLayers(frame
);
2542 EXPECT_TRUE(layer
->will_draw_called());
2543 EXPECT_TRUE(layer
->append_quads_called());
2544 EXPECT_TRUE(layer
->did_draw_called());
2547 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2550 LayerTreeHostImpl::FrameData frame
;
2552 layer
->set_will_draw_returns_false();
2553 layer
->ClearDidDrawCheck();
2555 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2556 host_impl_
->DrawLayers(&frame
);
2557 host_impl_
->DidDrawAllLayers(frame
);
2559 EXPECT_TRUE(layer
->will_draw_called());
2560 EXPECT_FALSE(layer
->append_quads_called());
2561 EXPECT_FALSE(layer
->did_draw_called());
2565 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2566 // The root layer is always drawn, so run this test on a child layer that
2567 // will be masked out by the root layer's bounds.
2568 host_impl_
->active_tree()->SetRootLayer(
2569 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2570 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2571 host_impl_
->active_tree()->root_layer());
2572 root
->SetMasksToBounds(true);
2573 root
->SetHasRenderSurface(true);
2574 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2575 DidDrawCheckLayer
* layer
=
2576 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2577 // Ensure visible_layer_rect for layer is empty.
2578 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2579 layer
->SetBounds(gfx::Size(10, 10));
2581 LayerTreeHostImpl::FrameData frame
;
2583 EXPECT_FALSE(layer
->will_draw_called());
2584 EXPECT_FALSE(layer
->did_draw_called());
2586 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
2587 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2588 host_impl_
->DrawLayers(&frame
);
2589 host_impl_
->DidDrawAllLayers(frame
);
2591 EXPECT_FALSE(layer
->will_draw_called());
2592 EXPECT_FALSE(layer
->did_draw_called());
2594 EXPECT_TRUE(layer
->visible_layer_rect().IsEmpty());
2596 // Ensure visible_layer_rect for layer is not empty
2597 layer
->SetPosition(gfx::PointF());
2599 EXPECT_FALSE(layer
->will_draw_called());
2600 EXPECT_FALSE(layer
->did_draw_called());
2602 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2603 host_impl_
->DrawLayers(&frame
);
2604 host_impl_
->DidDrawAllLayers(frame
);
2606 EXPECT_TRUE(layer
->will_draw_called());
2607 EXPECT_TRUE(layer
->did_draw_called());
2609 EXPECT_FALSE(layer
->visible_layer_rect().IsEmpty());
2612 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2613 gfx::Size
big_size(1000, 1000);
2614 host_impl_
->SetViewportSize(big_size
);
2616 host_impl_
->active_tree()->SetRootLayer(
2617 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2618 DidDrawCheckLayer
* root
=
2619 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2621 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2622 DidDrawCheckLayer
* occluded_layer
=
2623 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2625 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2626 root
->SetHasRenderSurface(true);
2627 DidDrawCheckLayer
* top_layer
=
2628 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2629 // This layer covers the occluded_layer above. Make this layer large so it can
2631 top_layer
->SetBounds(big_size
);
2632 top_layer
->SetContentsOpaque(true);
2634 LayerTreeHostImpl::FrameData frame
;
2636 EXPECT_FALSE(occluded_layer
->will_draw_called());
2637 EXPECT_FALSE(occluded_layer
->did_draw_called());
2638 EXPECT_FALSE(top_layer
->will_draw_called());
2639 EXPECT_FALSE(top_layer
->did_draw_called());
2641 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2642 host_impl_
->DrawLayers(&frame
);
2643 host_impl_
->DidDrawAllLayers(frame
);
2645 EXPECT_FALSE(occluded_layer
->will_draw_called());
2646 EXPECT_FALSE(occluded_layer
->did_draw_called());
2647 EXPECT_TRUE(top_layer
->will_draw_called());
2648 EXPECT_TRUE(top_layer
->did_draw_called());
2651 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2652 host_impl_
->active_tree()->SetRootLayer(
2653 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2654 DidDrawCheckLayer
* root
=
2655 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2657 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2658 root
->SetHasRenderSurface(true);
2659 DidDrawCheckLayer
* layer1
=
2660 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2662 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2663 DidDrawCheckLayer
* layer2
=
2664 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2666 layer1
->SetHasRenderSurface(true);
2667 layer1
->SetShouldFlattenTransform(true);
2669 EXPECT_FALSE(root
->did_draw_called());
2670 EXPECT_FALSE(layer1
->did_draw_called());
2671 EXPECT_FALSE(layer2
->did_draw_called());
2673 LayerTreeHostImpl::FrameData frame
;
2674 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2675 host_impl_
->active_tree()->root_layer());
2676 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2677 host_impl_
->DrawLayers(&frame
);
2678 host_impl_
->DidDrawAllLayers(frame
);
2680 EXPECT_TRUE(root
->did_draw_called());
2681 EXPECT_TRUE(layer1
->did_draw_called());
2682 EXPECT_TRUE(layer2
->did_draw_called());
2684 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2685 EXPECT_TRUE(layer1
->render_surface());
2688 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2690 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2693 bool had_incomplete_tile
,
2695 ResourceProvider
* resource_provider
) {
2696 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2699 had_incomplete_tile
,
2701 resource_provider
));
2704 void AppendQuads(RenderPass
* render_pass
,
2705 AppendQuadsData
* append_quads_data
) override
{
2706 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2707 if (had_incomplete_tile_
)
2708 append_quads_data
->num_incomplete_tiles
++;
2710 append_quads_data
->num_missing_tiles
++;
2714 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2717 bool had_incomplete_tile
,
2719 ResourceProvider
* resource_provider
)
2720 : DidDrawCheckLayer(tree_impl
, id
),
2721 tile_missing_(tile_missing
),
2722 had_incomplete_tile_(had_incomplete_tile
) {
2724 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2728 bool had_incomplete_tile_
;
2731 struct PrepareToDrawSuccessTestCase
{
2733 bool has_missing_tile
= false;
2734 bool has_incomplete_tile
= false;
2735 bool is_animating
= false;
2736 bool has_copy_request
= false;
2738 bool high_res_required
= false;
2740 State layer_between
;
2742 DrawResult expected_result
;
2744 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2745 : expected_result(result
) {}
2748 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2749 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2752 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2753 // 1. Animated layer first.
2754 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2755 cases
.back().layer_before
.is_animating
= true;
2756 // 2. Animated layer between.
2757 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2758 cases
.back().layer_between
.is_animating
= true;
2759 // 3. Animated layer last.
2760 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2761 cases
.back().layer_after
.is_animating
= true;
2762 // 4. Missing tile first.
2763 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2764 cases
.back().layer_before
.has_missing_tile
= true;
2765 // 5. Missing tile between.
2766 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2767 cases
.back().layer_between
.has_missing_tile
= true;
2768 // 6. Missing tile last.
2769 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2770 cases
.back().layer_after
.has_missing_tile
= true;
2771 // 7. Incomplete tile first.
2772 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2773 cases
.back().layer_before
.has_incomplete_tile
= true;
2774 // 8. Incomplete tile between.
2775 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2776 cases
.back().layer_between
.has_incomplete_tile
= true;
2777 // 9. Incomplete tile last.
2778 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2779 cases
.back().layer_after
.has_incomplete_tile
= true;
2780 // 10. Animation with missing tile.
2782 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2783 cases
.back().layer_between
.has_missing_tile
= true;
2784 cases
.back().layer_between
.is_animating
= true;
2785 // 11. Animation with incomplete tile.
2786 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2787 cases
.back().layer_between
.has_incomplete_tile
= true;
2788 cases
.back().layer_between
.is_animating
= true;
2790 // 12. High res required.
2791 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2792 cases
.back().high_res_required
= true;
2793 // 13. High res required with incomplete tile.
2795 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2796 cases
.back().high_res_required
= true;
2797 cases
.back().layer_between
.has_incomplete_tile
= true;
2798 // 14. High res required with missing tile.
2800 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2801 cases
.back().high_res_required
= true;
2802 cases
.back().layer_between
.has_missing_tile
= true;
2804 // 15. High res required is higher priority than animating missing tiles.
2806 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2807 cases
.back().high_res_required
= true;
2808 cases
.back().layer_between
.has_missing_tile
= true;
2809 cases
.back().layer_after
.has_missing_tile
= true;
2810 cases
.back().layer_after
.is_animating
= true;
2811 // 16. High res required is higher priority than animating missing tiles.
2813 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2814 cases
.back().high_res_required
= true;
2815 cases
.back().layer_between
.has_missing_tile
= true;
2816 cases
.back().layer_before
.has_missing_tile
= true;
2817 cases
.back().layer_before
.is_animating
= true;
2819 host_impl_
->active_tree()->SetRootLayer(
2820 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2821 DidDrawCheckLayer
* root
=
2822 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2823 root
->SetHasRenderSurface(true);
2825 LayerTreeHostImpl::FrameData frame
;
2826 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2827 host_impl_
->DrawLayers(&frame
);
2828 host_impl_
->DidDrawAllLayers(frame
);
2829 host_impl_
->SwapBuffers(frame
);
2831 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2832 const auto& testcase
= cases
[i
];
2833 std::vector
<LayerImpl
*> to_remove
;
2834 for (auto* child
: root
->children())
2835 to_remove
.push_back(child
);
2836 for (auto* child
: to_remove
)
2837 root
->RemoveChild(child
);
2839 std::ostringstream scope
;
2840 scope
<< "Test case: " << i
;
2841 SCOPED_TRACE(scope
.str());
2843 root
->AddChild(MissingTextureAnimatingLayer::Create(
2844 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2845 testcase
.layer_before
.has_incomplete_tile
,
2846 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2847 DidDrawCheckLayer
* before
=
2848 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2849 if (testcase
.layer_before
.has_copy_request
)
2850 before
->AddCopyRequest();
2852 root
->AddChild(MissingTextureAnimatingLayer::Create(
2853 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2854 testcase
.layer_between
.has_incomplete_tile
,
2855 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2856 DidDrawCheckLayer
* between
=
2857 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2858 if (testcase
.layer_between
.has_copy_request
)
2859 between
->AddCopyRequest();
2861 root
->AddChild(MissingTextureAnimatingLayer::Create(
2862 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2863 testcase
.layer_after
.has_incomplete_tile
,
2864 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2865 DidDrawCheckLayer
* after
=
2866 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2867 if (testcase
.layer_after
.has_copy_request
)
2868 after
->AddCopyRequest();
2870 if (testcase
.high_res_required
)
2871 host_impl_
->SetRequiresHighResToDraw();
2873 LayerTreeHostImpl::FrameData frame
;
2874 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2875 host_impl_
->DrawLayers(&frame
);
2876 host_impl_
->DidDrawAllLayers(frame
);
2877 host_impl_
->SwapBuffers(frame
);
2881 TEST_F(LayerTreeHostImplTest
,
2882 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2883 CreateHostImpl(DefaultSettings(),
2884 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2885 EXPECT_TRUE(host_impl_
->output_surface()
2887 .draw_and_swap_full_viewport_every_frame
);
2889 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2892 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2893 // 1. Animation with missing tile.
2894 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2895 cases
.back().layer_between
.has_missing_tile
= true;
2896 cases
.back().layer_between
.is_animating
= true;
2897 // 2. High res required with incomplete tile.
2898 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2899 cases
.back().high_res_required
= true;
2900 cases
.back().layer_between
.has_incomplete_tile
= true;
2901 // 3. High res required with missing tile.
2902 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2903 cases
.back().high_res_required
= true;
2904 cases
.back().layer_between
.has_missing_tile
= true;
2906 host_impl_
->active_tree()->SetRootLayer(
2907 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2908 DidDrawCheckLayer
* root
=
2909 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2910 root
->SetHasRenderSurface(true);
2912 LayerTreeHostImpl::FrameData frame
;
2913 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2914 host_impl_
->DrawLayers(&frame
);
2915 host_impl_
->DidDrawAllLayers(frame
);
2916 host_impl_
->SwapBuffers(frame
);
2918 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2919 const auto& testcase
= cases
[i
];
2920 std::vector
<LayerImpl
*> to_remove
;
2921 for (auto* child
: root
->children())
2922 to_remove
.push_back(child
);
2923 for (auto* child
: to_remove
)
2924 root
->RemoveChild(child
);
2926 std::ostringstream scope
;
2927 scope
<< "Test case: " << i
;
2928 SCOPED_TRACE(scope
.str());
2930 root
->AddChild(MissingTextureAnimatingLayer::Create(
2931 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2932 testcase
.layer_before
.has_incomplete_tile
,
2933 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2934 DidDrawCheckLayer
* before
=
2935 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2936 if (testcase
.layer_before
.has_copy_request
)
2937 before
->AddCopyRequest();
2939 root
->AddChild(MissingTextureAnimatingLayer::Create(
2940 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2941 testcase
.layer_between
.has_incomplete_tile
,
2942 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2943 DidDrawCheckLayer
* between
=
2944 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2945 if (testcase
.layer_between
.has_copy_request
)
2946 between
->AddCopyRequest();
2948 root
->AddChild(MissingTextureAnimatingLayer::Create(
2949 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2950 testcase
.layer_after
.has_incomplete_tile
,
2951 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2952 DidDrawCheckLayer
* after
=
2953 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2954 if (testcase
.layer_after
.has_copy_request
)
2955 after
->AddCopyRequest();
2957 if (testcase
.high_res_required
)
2958 host_impl_
->SetRequiresHighResToDraw();
2960 LayerTreeHostImpl::FrameData frame
;
2961 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2962 host_impl_
->DrawLayers(&frame
);
2963 host_impl_
->DidDrawAllLayers(frame
);
2964 host_impl_
->SwapBuffers(frame
);
2968 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2969 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2970 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2971 root
->SetHasRenderSurface(true);
2972 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2975 // Scroll event is ignored because layer is not scrollable.
2976 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2977 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2978 EXPECT_FALSE(did_request_redraw_
);
2979 EXPECT_FALSE(did_request_commit_
);
2982 TEST_F(LayerTreeHostImplTest
, ClampingAfterActivation
) {
2983 host_impl_
->CreatePendingTree();
2984 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2985 CreateScrollAndContentsLayers(host_impl_
->pending_tree(),
2986 gfx::Size(100, 100));
2987 host_impl_
->ActivateSyncTree();
2989 host_impl_
->CreatePendingTree();
2990 const gfx::ScrollOffset pending_scroll
= gfx::ScrollOffset(-100, -100);
2991 LayerImpl
* active_outer_layer
=
2992 host_impl_
->active_tree()->OuterViewportScrollLayer();
2993 LayerImpl
* pending_outer_layer
=
2994 host_impl_
->pending_tree()->OuterViewportScrollLayer();
2995 pending_outer_layer
->PushScrollOffsetFromMainThread(pending_scroll
);
2997 host_impl_
->ActivateSyncTree();
2998 // Scrolloffsets on the active tree will be clamped after activation.
2999 EXPECT_EQ(active_outer_layer
->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
3002 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
3004 LayerTreeHostImplTopControlsTest()
3005 // Make the clip size the same as the layer (content) size so the layer is
3007 : layer_size_(10, 10),
3008 clip_size_(layer_size_
),
3009 top_controls_height_(50) {
3010 viewport_size_
= gfx::Size(clip_size_
.width(),
3011 clip_size_
.height() + top_controls_height_
);
3014 bool CreateHostImpl(const LayerTreeSettings
& settings
,
3015 scoped_ptr
<OutputSurface
> output_surface
) override
{
3017 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
3019 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
3020 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3021 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
3026 void SetupTopControlsAndScrollLayerWithVirtualViewport(
3027 const gfx::Size
& inner_viewport_size
,
3028 const gfx::Size
& outer_viewport_size
,
3029 const gfx::Size
& scroll_layer_size
) {
3030 CreateHostImpl(settings_
, CreateOutputSurface());
3031 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3032 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
3033 host_impl_
->DidChangeTopControlsPosition();
3035 scoped_ptr
<LayerImpl
> root
=
3036 LayerImpl::Create(host_impl_
->active_tree(), 1);
3037 scoped_ptr
<LayerImpl
> root_clip
=
3038 LayerImpl::Create(host_impl_
->active_tree(), 2);
3039 scoped_ptr
<LayerImpl
> page_scale
=
3040 LayerImpl::Create(host_impl_
->active_tree(), 3);
3042 scoped_ptr
<LayerImpl
> outer_scroll
=
3043 LayerImpl::Create(host_impl_
->active_tree(), 4);
3044 scoped_ptr
<LayerImpl
> outer_clip
=
3045 LayerImpl::Create(host_impl_
->active_tree(), 5);
3047 root_clip
->SetBounds(inner_viewport_size
);
3048 root
->SetScrollClipLayer(root_clip
->id());
3049 root
->SetBounds(outer_viewport_size
);
3050 root
->SetPosition(gfx::PointF());
3051 root
->SetDrawsContent(false);
3052 root
->SetIsContainerForFixedPositionLayers(true);
3053 root_clip
->SetHasRenderSurface(true);
3054 outer_clip
->SetBounds(outer_viewport_size
);
3055 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
3056 outer_scroll
->SetBounds(scroll_layer_size
);
3057 outer_scroll
->SetPosition(gfx::PointF());
3058 outer_scroll
->SetDrawsContent(false);
3059 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
3061 int inner_viewport_scroll_layer_id
= root
->id();
3062 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
3063 int page_scale_layer_id
= page_scale
->id();
3065 outer_clip
->AddChild(outer_scroll
.Pass());
3066 root
->AddChild(outer_clip
.Pass());
3067 page_scale
->AddChild(root
.Pass());
3068 root_clip
->AddChild(page_scale
.Pass());
3070 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3071 host_impl_
->active_tree()->SetViewportLayersFromIds(
3072 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
3073 outer_viewport_scroll_layer_id
);
3075 host_impl_
->SetViewportSize(inner_viewport_size
);
3076 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3077 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
3081 gfx::Size layer_size_
;
3082 gfx::Size clip_size_
;
3083 gfx::Size viewport_size_
;
3084 float top_controls_height_
;
3086 LayerTreeSettings settings_
;
3087 }; // class LayerTreeHostImplTopControlsTest
3089 // Tests that, on a page with content the same size as the viewport, hiding
3090 // the top controls also increases the ScrollableSize (i.e. the content size).
3091 // Since the viewport got larger, the effective scrollable "content" also did.
3092 // This ensures, for one thing, that the overscroll glow is shown in the right
3094 TEST_F(LayerTreeHostImplTopControlsTest
,
3095 HidingTopControlsExpandsScrollableSize
) {
3096 SetupTopControlsAndScrollLayerWithVirtualViewport(
3097 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
3099 LayerTreeImpl
* active_tree
= host_impl_
->active_tree();
3101 // Create a content layer beneath the outer viewport scroll layer.
3102 int id
= host_impl_
->OuterViewportScrollLayer()->id();
3103 host_impl_
->OuterViewportScrollLayer()->AddChild(
3104 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2));
3105 LayerImpl
* content
= active_tree
->OuterViewportScrollLayer()->children()[0];
3106 content
->SetBounds(gfx::Size(50, 50));
3110 LayerImpl
* inner_container
= active_tree
->InnerViewportContainerLayer();
3111 LayerImpl
* outer_container
= active_tree
->OuterViewportContainerLayer();
3113 // The top controls should start off showing so the viewport should be shrunk.
3114 ASSERT_EQ(gfx::Size(50, 50), inner_container
->bounds());
3115 ASSERT_EQ(gfx::Size(50, 50), outer_container
->bounds());
3117 EXPECT_EQ(gfx::SizeF(50, 50), active_tree
->ScrollableSize());
3119 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3120 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3122 host_impl_
->top_controls_manager()->ScrollBegin();
3124 // Hide the top controls by a bit, the scrollable size should increase but the
3125 // actual content bounds shouldn't.
3127 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3128 ASSERT_EQ(gfx::Size(50, 75), inner_container
->bounds());
3129 ASSERT_EQ(gfx::Size(50, 75), outer_container
->bounds());
3130 EXPECT_EQ(gfx::SizeF(50, 75), active_tree
->ScrollableSize());
3131 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3134 // Fully hide the top controls.
3136 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3137 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3138 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3139 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3140 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3143 // Scrolling additionally shouldn't have any effect.
3145 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3146 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3147 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3148 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3149 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3152 host_impl_
->top_controls_manager()->ScrollEnd();
3153 host_impl_
->ScrollEnd();
3156 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
3157 SetupTopControlsAndScrollLayerWithVirtualViewport(
3158 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
3161 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3162 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3164 // Make the test scroll delta a fractional amount, to verify that the
3165 // fixed container size delta is (1) non-zero, and (2) fractional, and
3166 // (3) matches the movement of the top controls.
3167 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
3168 host_impl_
->top_controls_manager()->ScrollBegin();
3169 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3170 host_impl_
->top_controls_manager()->ScrollEnd();
3172 LayerImpl
* inner_viewport_scroll_layer
=
3173 host_impl_
->active_tree()->InnerViewportScrollLayer();
3174 DCHECK(inner_viewport_scroll_layer
);
3175 host_impl_
->ScrollEnd();
3176 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3177 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3180 // In this test, the outer viewport is initially unscrollable. We test that a
3181 // scroll initiated on the inner viewport, causing the top controls to show and
3182 // thus making the outer viewport scrollable, still scrolls the outer viewport.
3183 TEST_F(LayerTreeHostImplTopControlsTest
,
3184 TopControlsOuterViewportBecomesScrollable
) {
3185 SetupTopControlsAndScrollLayerWithVirtualViewport(
3186 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
3189 LayerImpl
* inner_scroll
=
3190 host_impl_
->active_tree()->InnerViewportScrollLayer();
3191 LayerImpl
* inner_container
=
3192 host_impl_
->active_tree()->InnerViewportContainerLayer();
3193 LayerImpl
* outer_scroll
=
3194 host_impl_
->active_tree()->OuterViewportScrollLayer();
3195 LayerImpl
* outer_container
=
3196 host_impl_
->active_tree()->OuterViewportContainerLayer();
3198 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
3199 outer_scroll
->SetDrawsContent(true);
3200 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
3202 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3203 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3204 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
3206 // The entire scroll delta should have been used to hide the top controls.
3207 // The viewport layers should be resized back to their full sizes.
3208 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3209 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3210 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
3211 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
3213 // The inner viewport should be scrollable by 50px * page_scale.
3214 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
3215 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
3216 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3217 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
3219 host_impl_
->ScrollEnd();
3221 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3222 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3223 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
3225 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3227 // The entire scroll delta should have been used to show the top controls.
3228 // The outer viewport should be resized to accomodate and scrolled to the
3229 // bottom of the document to keep the viewport in place.
3230 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3231 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
3232 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
3233 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3234 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3236 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3237 // since it wasn't scrollable when the scroll began.
3238 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
3239 EXPECT_EQ(15.f
, outer_scroll
->CurrentScrollOffset().y());
3240 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3242 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
3243 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3244 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3246 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3247 host_impl_
->ScrollEnd();
3249 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3250 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3253 // Test that the fixed position container delta is appropriately adjusted
3254 // by the top controls showing/hiding and page scale doesn't affect it.
3255 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
3256 SetupTopControlsAndScrollLayerWithVirtualViewport(
3257 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3259 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3261 float page_scale
= 1.5f
;
3262 LayerImpl
* outer_viewport_scroll_layer
=
3263 host_impl_
->active_tree()->OuterViewportScrollLayer();
3265 // Zoom in, since the fixed container is the outer viewport, the delta should
3267 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3269 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3270 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3272 // Scroll down, the top controls hiding should expand the viewport size so
3273 // the delta should be equal to the scroll distance.
3274 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
3275 host_impl_
->top_controls_manager()->ScrollBegin();
3276 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3277 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
3278 host_impl_
->top_controls_manager()->ContentTopOffset());
3279 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3280 outer_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3281 host_impl_
->ScrollEnd();
3283 // Scroll past the maximum extent. The delta shouldn't be greater than the
3284 // top controls height.
3285 host_impl_
->top_controls_manager()->ScrollBegin();
3286 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3287 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3288 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3289 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3290 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
3291 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3292 host_impl_
->ScrollEnd();
3294 // Scroll in the direction to make the top controls show.
3295 host_impl_
->top_controls_manager()->ScrollBegin();
3296 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
3297 EXPECT_EQ(top_controls_scroll_delta
.y(),
3298 host_impl_
->top_controls_manager()->ContentTopOffset());
3300 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
3301 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3302 host_impl_
->top_controls_manager()->ScrollEnd();
3305 // Test that if only the top controls are scrolled, we shouldn't request a
3307 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsDontTriggerCommit
) {
3308 SetupTopControlsAndScrollLayerWithVirtualViewport(
3309 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3312 // Show top controls
3313 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3315 // Scroll 25px to hide top controls
3316 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3317 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3318 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3319 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3320 EXPECT_FALSE(did_request_commit_
);
3323 // Test that if a scrollable sublayer doesn't consume the scroll,
3324 // top controls should hide when scrolling down.
3325 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
3326 gfx::Size
sub_content_size(100, 400);
3327 gfx::Size
sub_content_layer_size(100, 300);
3328 SetupTopControlsAndScrollLayerWithVirtualViewport(
3329 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3332 // Show top controls
3333 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3335 LayerImpl
* outer_viewport_scroll_layer
=
3336 host_impl_
->active_tree()->OuterViewportScrollLayer();
3337 int id
= outer_viewport_scroll_layer
->id();
3339 scoped_ptr
<LayerImpl
> child
=
3340 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
3341 scoped_ptr
<LayerImpl
> child_clip
=
3342 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
3344 child_clip
->SetBounds(sub_content_layer_size
);
3345 child
->SetScrollClipLayer(child_clip
->id());
3346 child
->SetBounds(sub_content_size
);
3347 child
->SetPosition(gfx::PointF());
3348 child
->SetDrawsContent(true);
3349 child
->SetIsContainerForFixedPositionLayers(true);
3351 // scroll child to limit
3352 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
3353 child_clip
->AddChild(child
.Pass());
3354 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
3356 // Scroll 25px to hide top controls
3357 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3358 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3359 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3360 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3361 host_impl_
->ScrollEnd();
3363 // Top controls should be hidden
3364 EXPECT_EQ(scroll_delta
.y(),
3365 top_controls_height_
-
3366 host_impl_
->top_controls_manager()->ContentTopOffset());
3369 // Ensure setting the top controls position explicitly using the setters on the
3370 // TreeImpl correctly affects the top controls manager and viewport bounds.
3371 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
3372 CreateHostImpl(settings_
, CreateOutputSurface());
3373 SetupTopControlsAndScrollLayerWithVirtualViewport(
3374 layer_size_
, layer_size_
, layer_size_
);
3377 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3378 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3379 30.f
/ top_controls_height_
);
3380 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3381 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3382 EXPECT_FLOAT_EQ(-20.f
,
3383 host_impl_
->top_controls_manager()->ControlsTopOffset());
3385 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3386 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3387 EXPECT_FLOAT_EQ(-50.f
,
3388 host_impl_
->top_controls_manager()->ControlsTopOffset());
3390 host_impl_
->DidChangeTopControlsPosition();
3392 // Now that top controls have moved, expect the clip to resize.
3393 LayerImpl
* inner_clip_ptr
=
3394 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3395 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3398 // Test that the top_controls delta and sent delta are appropriately
3399 // applied on sync tree activation. The total top controls offset shouldn't
3400 // change after the activation.
3401 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
3402 CreateHostImpl(settings_
, CreateOutputSurface());
3403 SetupTopControlsAndScrollLayerWithVirtualViewport(
3404 layer_size_
, layer_size_
, layer_size_
);
3407 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3408 20.f
/ top_controls_height_
);
3409 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3410 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
3411 15.f
/ top_controls_height_
);
3412 host_impl_
->active_tree()
3413 ->top_controls_shown_ratio()
3414 ->PullDeltaForMainThread();
3415 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3416 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
3417 top_controls_height_
);
3419 host_impl_
->DidChangeTopControlsPosition();
3420 LayerImpl
* inner_clip_ptr
=
3421 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3422 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3423 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3425 host_impl_
->ActivateSyncTree();
3427 inner_clip_ptr
= host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3428 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3429 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3432 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
3433 top_controls_height_
);
3436 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3437 top_controls_height_
);
3440 // Test that changing the top controls layout height is correctly applied to
3441 // the inner viewport container bounds. That is, the top controls layout
3442 // height is the amount that the inner viewport container was shrunk outside
3443 // the compositor to accommodate the top controls.
3444 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
3445 CreateHostImpl(settings_
, CreateOutputSurface());
3446 SetupTopControlsAndScrollLayerWithVirtualViewport(
3447 layer_size_
, layer_size_
, layer_size_
);
3450 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
3451 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3453 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3455 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3456 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3458 host_impl_
->DidChangeTopControlsPosition();
3459 LayerImpl
* inner_clip_ptr
=
3460 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3461 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3462 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3464 host_impl_
->sync_tree()->root_layer()->SetBounds(
3465 gfx::Size(inner_clip_ptr
->bounds().width(),
3466 inner_clip_ptr
->bounds().height() - 50.f
));
3468 host_impl_
->ActivateSyncTree();
3471 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3472 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3474 // The total bounds should remain unchanged since the bounds delta should
3475 // account for the difference between the layout height and the current
3476 // top controls offset.
3477 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3478 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), inner_clip_ptr
->bounds_delta());
3480 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3481 host_impl_
->DidChangeTopControlsPosition();
3483 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
3484 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
3485 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3486 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), inner_clip_ptr
->bounds_delta());
3487 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
3488 inner_clip_ptr
->bounds());
3491 // Test that showing/hiding the top controls when the viewport is fully scrolled
3492 // doesn't incorrectly change the viewport offset due to clamping from changing
3494 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
3495 SetupTopControlsAndScrollLayerWithVirtualViewport(
3496 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3499 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3501 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3502 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3504 // Scroll the viewports to max scroll offset.
3505 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3506 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3508 gfx::ScrollOffset viewport_offset
=
3509 host_impl_
->active_tree()->TotalScrollOffset();
3510 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
3512 // Hide the top controls by 25px.
3513 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3514 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3515 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3516 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3518 // scrolling down at the max extents no longer hides the top controls
3519 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3521 // forcefully hide the top controls by 25px
3522 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3523 host_impl_
->ScrollEnd();
3525 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3526 top_controls_height_
-
3527 host_impl_
->top_controls_manager()->ContentTopOffset());
3529 inner_scroll
->ClampScrollToMaxScrollOffset();
3530 outer_scroll
->ClampScrollToMaxScrollOffset();
3532 // We should still be fully scrolled.
3533 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3534 host_impl_
->active_tree()->TotalScrollOffset());
3536 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3538 // Bring the top controls down by 25px.
3539 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3540 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3541 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3542 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3543 host_impl_
->ScrollEnd();
3545 // The viewport offset shouldn't have changed.
3546 EXPECT_EQ(viewport_offset
,
3547 host_impl_
->active_tree()->TotalScrollOffset());
3549 // Scroll the viewports to max scroll offset.
3550 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3551 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3552 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3553 host_impl_
->active_tree()->TotalScrollOffset());
3556 // Test that the top controls coming in and out maintains the same aspect ratio
3557 // between the inner and outer viewports.
3558 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3559 SetupTopControlsAndScrollLayerWithVirtualViewport(
3560 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3561 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 2.f
);
3564 EXPECT_FLOAT_EQ(top_controls_height_
,
3565 host_impl_
->top_controls_manager()->ContentTopOffset());
3567 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3568 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3569 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3570 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3571 host_impl_
->ScrollEnd();
3573 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3574 top_controls_height_
-
3575 host_impl_
->top_controls_manager()->ContentTopOffset());
3577 // Top controls were hidden by 25px so the inner viewport should have expanded
3579 LayerImpl
* outer_container
=
3580 host_impl_
->active_tree()->OuterViewportContainerLayer();
3581 LayerImpl
* inner_container
=
3582 host_impl_
->active_tree()->InnerViewportContainerLayer();
3583 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3585 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3586 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3587 inner_container
->BoundsForScrolling().height();
3588 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3589 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3591 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3594 // Test that scrolling the outer viewport affects the top controls.
3595 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3596 SetupTopControlsAndScrollLayerWithVirtualViewport(
3597 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3600 EXPECT_EQ(top_controls_height_
,
3601 host_impl_
->top_controls_manager()->ContentTopOffset());
3603 // Send a gesture scroll that will scroll the outer viewport, make sure the
3604 // top controls get scrolled.
3605 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3606 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3607 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3608 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3609 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3610 host_impl_
->CurrentlyScrollingLayer());
3611 host_impl_
->ScrollEnd();
3613 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3614 top_controls_height_
-
3615 host_impl_
->top_controls_manager()->ContentTopOffset());
3617 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3618 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3619 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3620 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3622 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3623 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3624 host_impl_
->CurrentlyScrollingLayer());
3626 host_impl_
->ScrollEnd();
3628 // Position the viewports such that the inner viewport will be scrolled.
3629 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3630 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3631 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3633 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3634 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3635 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3636 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3638 EXPECT_EQ(top_controls_height_
,
3639 host_impl_
->top_controls_manager()->ContentTopOffset());
3641 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3642 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3644 host_impl_
->ScrollEnd();
3647 TEST_F(LayerTreeHostImplTopControlsTest
,
3648 ScrollNonScrollableRootWithTopControls
) {
3649 CreateHostImpl(settings_
, CreateOutputSurface());
3650 SetupTopControlsAndScrollLayerWithVirtualViewport(
3651 layer_size_
, layer_size_
, layer_size_
);
3654 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3655 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3657 host_impl_
->top_controls_manager()->ScrollBegin();
3658 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3659 host_impl_
->top_controls_manager()->ScrollEnd();
3660 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3661 // Now that top controls have moved, expect the clip to resize.
3662 LayerImpl
* inner_clip_ptr
=
3663 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3664 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3666 host_impl_
->ScrollEnd();
3668 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3669 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3671 float scroll_increment_y
= -25.f
;
3672 host_impl_
->top_controls_manager()->ScrollBegin();
3673 host_impl_
->top_controls_manager()->ScrollBy(
3674 gfx::Vector2dF(0.f
, scroll_increment_y
));
3675 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3676 host_impl_
->top_controls_manager()->ContentTopOffset());
3677 // Now that top controls have moved, expect the clip to resize.
3678 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3679 viewport_size_
.height() + scroll_increment_y
),
3680 inner_clip_ptr
->bounds());
3682 host_impl_
->top_controls_manager()->ScrollBy(
3683 gfx::Vector2dF(0.f
, scroll_increment_y
));
3684 host_impl_
->top_controls_manager()->ScrollEnd();
3685 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3686 host_impl_
->top_controls_manager()->ContentTopOffset());
3687 // Now that top controls have moved, expect the clip to resize.
3688 EXPECT_EQ(clip_size_
, inner_clip_ptr
->bounds());
3690 host_impl_
->ScrollEnd();
3692 // Verify the layer is once-again non-scrollable.
3694 gfx::ScrollOffset(),
3695 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3697 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3698 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3701 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3702 // Test the configuration where a non-composited root layer is embedded in a
3703 // scrollable outer layer.
3704 gfx::Size
surface_size(10, 10);
3705 gfx::Size
contents_size(20, 20);
3707 scoped_ptr
<LayerImpl
> content_layer
=
3708 LayerImpl::Create(host_impl_
->active_tree(), 1);
3709 content_layer
->SetDrawsContent(true);
3710 content_layer
->SetPosition(gfx::PointF());
3711 content_layer
->SetBounds(contents_size
);
3713 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3714 LayerImpl::Create(host_impl_
->active_tree(), 3);
3715 scroll_clip_layer
->SetBounds(surface_size
);
3717 scoped_ptr
<LayerImpl
> scroll_layer
=
3718 LayerImpl::Create(host_impl_
->active_tree(), 2);
3719 scroll_layer
->SetScrollClipLayer(3);
3720 scroll_layer
->SetBounds(contents_size
);
3721 scroll_layer
->SetPosition(gfx::PointF());
3722 scroll_layer
->AddChild(content_layer
.Pass());
3723 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3725 scroll_clip_layer
->SetHasRenderSurface(true);
3726 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3727 host_impl_
->SetViewportSize(surface_size
);
3730 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3731 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3732 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3733 host_impl_
->ScrollEnd();
3734 EXPECT_TRUE(did_request_redraw_
);
3735 EXPECT_TRUE(did_request_commit_
);
3738 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3739 gfx::Size
surface_size(10, 10);
3740 gfx::Size
contents_size(20, 20);
3741 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3742 root
->SetBounds(surface_size
);
3743 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3744 root
->SetHasRenderSurface(true);
3745 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3746 host_impl_
->SetViewportSize(surface_size
);
3749 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3750 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3751 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3752 host_impl_
->ScrollEnd();
3753 EXPECT_TRUE(did_request_redraw_
);
3754 EXPECT_TRUE(did_request_commit_
);
3757 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3758 gfx::Size
surface_size(10, 10);
3759 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3760 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3761 root
->SetHasRenderSurface(true);
3762 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3763 host_impl_
->SetViewportSize(surface_size
);
3766 // Scroll event is ignored because the input coordinate is outside the layer
3768 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3769 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3770 EXPECT_FALSE(did_request_redraw_
);
3771 EXPECT_FALSE(did_request_commit_
);
3774 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3775 gfx::Size
surface_size(10, 10);
3776 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3777 root
->SetHasRenderSurface(true);
3778 scoped_ptr
<LayerImpl
> child
=
3779 CreateScrollableLayer(2, surface_size
, root
.get());
3780 host_impl_
->SetViewportSize(surface_size
);
3782 gfx::Transform matrix
;
3783 matrix
.RotateAboutXAxis(180.0);
3784 child
->SetTransform(matrix
);
3785 child
->SetDoubleSided(false);
3787 root
->AddChild(child
.Pass());
3788 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3791 // Scroll event is ignored because the scrollable layer is not facing the
3792 // viewer and there is nothing scrollable behind it.
3793 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3794 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3795 EXPECT_FALSE(did_request_redraw_
);
3796 EXPECT_FALSE(did_request_commit_
);
3799 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3800 gfx::Size
surface_size(10, 10);
3801 scoped_ptr
<LayerImpl
> clip_layer
=
3802 LayerImpl::Create(host_impl_
->active_tree(), 3);
3803 scoped_ptr
<LayerImpl
> content_layer
=
3804 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3805 content_layer
->SetShouldScrollOnMainThread(true);
3806 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3808 // Note: we can use the same clip layer for both since both calls to
3809 // CreateScrollableLayer() use the same surface size.
3810 scoped_ptr
<LayerImpl
> scroll_layer
=
3811 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3812 scroll_layer
->AddChild(content_layer
.Pass());
3813 clip_layer
->AddChild(scroll_layer
.Pass());
3814 clip_layer
->SetHasRenderSurface(true);
3816 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3817 host_impl_
->SetViewportSize(surface_size
);
3820 // Scrolling fails because the content layer is asking to be scrolled on the
3822 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3823 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3826 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3827 gfx::Size
viewport_size(10, 10);
3828 float page_scale
= 2.f
;
3830 SetupScrollAndContentsLayers(viewport_size
);
3832 // Setup the layers so that the outer viewport is scrollable.
3833 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3835 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3837 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3840 LayerImpl
* root_scroll
=
3841 host_impl_
->active_tree()->OuterViewportScrollLayer();
3842 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3844 gfx::Vector2d
scroll_delta(0, 10);
3845 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3846 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3847 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3848 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3849 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3850 host_impl_
->ScrollEnd();
3852 // Set new page scale from main thread.
3853 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3855 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3856 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3857 expected_scroll_delta
));
3859 // The scroll range should also have been updated.
3860 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3862 // The page scale delta remains constant because the impl thread did not
3864 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3867 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3868 gfx::Size
viewport_size(10, 10);
3869 float page_scale
= 2.f
;
3871 SetupScrollAndContentsLayers(viewport_size
);
3873 // Setup the layers so that the outer viewport is scrollable.
3874 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3876 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3878 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3881 LayerImpl
* root_scroll
=
3882 host_impl_
->active_tree()->OuterViewportScrollLayer();
3883 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3885 gfx::Vector2d
scroll_delta(0, 10);
3886 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3887 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3888 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3889 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3890 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3891 host_impl_
->ScrollEnd();
3893 // Set new page scale on impl thread by pinching.
3894 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3895 host_impl_
->PinchGestureBegin();
3896 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3897 host_impl_
->PinchGestureEnd();
3898 host_impl_
->ScrollEnd();
3901 // The scroll delta is not scaled because the main thread did not scale.
3902 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3903 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll
->id(),
3904 expected_scroll_delta
));
3906 // The scroll range should also have been updated.
3907 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3909 // The page scale delta should match the new scale on the impl side.
3910 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3913 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3914 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3915 gfx::Size
surface_size(10, 10);
3916 float default_page_scale
= 1.f
;
3917 gfx::Transform default_page_scale_matrix
;
3918 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3920 float new_page_scale
= 2.f
;
3921 gfx::Transform new_page_scale_matrix
;
3922 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3924 // Create a normal scrollable root layer and another scrollable child layer.
3925 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3926 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3927 LayerImpl
* child
= scroll
->children()[0];
3929 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3930 LayerImpl::Create(host_impl_
->active_tree(), 6);
3931 scoped_ptr
<LayerImpl
> scrollable_child
=
3932 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3933 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3934 child
->AddChild(scrollable_child_clip
.Pass());
3935 LayerImpl
* grand_child
= child
->children()[0];
3937 // Set new page scale on impl thread by pinching.
3938 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3939 host_impl_
->PinchGestureBegin();
3940 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3941 host_impl_
->PinchGestureEnd();
3942 host_impl_
->ScrollEnd();
3945 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3946 // the page scale delta on the root layer is applied hierarchically.
3947 LayerTreeHostImpl::FrameData frame
;
3948 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3949 host_impl_
->DrawLayers(&frame
);
3950 host_impl_
->DidDrawAllLayers(frame
);
3952 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3953 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3954 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3955 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3956 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3957 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3958 EXPECT_EQ(new_page_scale
,
3959 grand_child
->draw_transform().matrix().getDouble(0, 0));
3960 EXPECT_EQ(new_page_scale
,
3961 grand_child
->draw_transform().matrix().getDouble(1, 1));
3964 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3965 gfx::Size
surface_size(30, 30);
3966 SetupScrollAndContentsLayers(surface_size
);
3968 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3970 // Make the outer scroll layer scrollable.
3971 outer_scroll
->SetBounds(gfx::Size(50, 50));
3975 gfx::Vector2d
scroll_delta(0, 10);
3976 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3977 gfx::ScrollOffset
expected_max_scroll(outer_scroll
->MaxScrollOffset());
3978 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3979 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3980 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3981 host_impl_
->ScrollEnd();
3983 float page_scale
= 2.f
;
3984 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3989 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3990 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), outer_scroll
->id(),
3991 expected_scroll_delta
));
3993 // The scroll range should not have changed.
3994 EXPECT_EQ(outer_scroll
->MaxScrollOffset(), expected_max_scroll
);
3996 // The page scale delta remains constant because the impl thread did not
3998 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
4001 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
4002 // Scroll a child layer beyond its maximum scroll range and make sure the
4003 // parent layer is scrolled on the axis on which the child was unable to
4005 gfx::Size
surface_size(10, 10);
4006 gfx::Size
content_size(20, 20);
4007 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4008 root
->SetBounds(surface_size
);
4009 root
->SetHasRenderSurface(true);
4010 scoped_ptr
<LayerImpl
> grand_child
=
4011 CreateScrollableLayer(3, content_size
, root
.get());
4013 scoped_ptr
<LayerImpl
> child
=
4014 CreateScrollableLayer(2, content_size
, root
.get());
4015 LayerImpl
* grand_child_layer
= grand_child
.get();
4016 child
->AddChild(grand_child
.Pass());
4018 LayerImpl
* child_layer
= child
.get();
4019 root
->AddChild(child
.Pass());
4020 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4021 host_impl_
->active_tree()->DidBecomeActive();
4022 host_impl_
->SetViewportSize(surface_size
);
4023 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
4024 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
4028 gfx::Vector2d
scroll_delta(-8, -7);
4029 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4030 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4031 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4032 host_impl_
->ScrollEnd();
4034 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4035 host_impl_
->ProcessScrollDeltas();
4037 // The grand child should have scrolled up to its limit.
4038 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
4039 LayerImpl
* grand_child
= child
->children()[0];
4040 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4041 gfx::Vector2d(0, -5)));
4043 // The child should have only scrolled on the other axis.
4044 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4045 gfx::Vector2d(-3, 0)));
4049 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
4050 // Scroll a child layer beyond its maximum scroll range and make sure the
4051 // the scroll doesn't bubble up to the parent layer.
4052 gfx::Size
surface_size(20, 20);
4053 gfx::Size
viewport_size(10, 10);
4054 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4055 root
->SetHasRenderSurface(true);
4056 scoped_ptr
<LayerImpl
> root_scrolling
=
4057 CreateScrollableLayer(2, surface_size
, root
.get());
4058 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
4060 scoped_ptr
<LayerImpl
> grand_child
=
4061 CreateScrollableLayer(4, surface_size
, root
.get());
4063 scoped_ptr
<LayerImpl
> child
=
4064 CreateScrollableLayer(3, surface_size
, root
.get());
4065 LayerImpl
* grand_child_layer
= grand_child
.get();
4066 child
->AddChild(grand_child
.Pass());
4068 LayerImpl
* child_layer
= child
.get();
4069 root_scrolling
->AddChild(child
.Pass());
4070 root
->AddChild(root_scrolling
.Pass());
4071 EXPECT_EQ(viewport_size
, root
->bounds());
4072 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4073 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4075 host_impl_
->active_tree()->DidBecomeActive();
4076 host_impl_
->SetViewportSize(viewport_size
);
4078 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4079 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4083 gfx::Vector2d
scroll_delta(0, -10);
4084 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4085 host_impl_
->ScrollBegin(gfx::Point(),
4086 InputHandler::NON_BUBBLING_GESTURE
));
4087 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4088 host_impl_
->ScrollEnd();
4090 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4091 host_impl_
->ProcessScrollDeltas();
4093 // The grand child should have scrolled up to its limit.
4095 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
4096 LayerImpl
* grand_child
= child
->children()[0];
4097 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4098 gfx::Vector2d(0, -2)));
4100 // The child should not have scrolled.
4101 ExpectNone(*scroll_info
.get(), child
->id());
4103 // The next time we scroll we should only scroll the parent.
4104 scroll_delta
= gfx::Vector2d(0, -3);
4105 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4106 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4107 InputHandler::NON_BUBBLING_GESTURE
));
4108 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4109 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4110 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
4111 host_impl_
->ScrollEnd();
4113 scroll_info
= host_impl_
->ProcessScrollDeltas();
4115 // The child should have scrolled up to its limit.
4116 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4117 gfx::Vector2d(0, -3)));
4119 // The grand child should not have scrolled.
4120 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4121 gfx::Vector2d(0, -2)));
4123 // After scrolling the parent, another scroll on the opposite direction
4124 // should still scroll the child.
4125 scroll_delta
= gfx::Vector2d(0, 7);
4126 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4127 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4128 InputHandler::NON_BUBBLING_GESTURE
));
4129 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4130 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4131 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4132 host_impl_
->ScrollEnd();
4134 scroll_info
= host_impl_
->ProcessScrollDeltas();
4136 // The grand child should have scrolled.
4137 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4138 gfx::Vector2d(0, 5)));
4140 // The child should not have scrolled.
4141 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4142 gfx::Vector2d(0, -3)));
4144 // Scrolling should be adjusted from viewport space.
4145 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
4146 host_impl_
->SetPageScaleOnActiveTree(2.f
);
4148 scroll_delta
= gfx::Vector2d(0, -2);
4149 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4150 host_impl_
->ScrollBegin(gfx::Point(1, 1),
4151 InputHandler::NON_BUBBLING_GESTURE
));
4152 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
4153 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4154 host_impl_
->ScrollEnd();
4156 scroll_info
= host_impl_
->ProcessScrollDeltas();
4158 // Should have scrolled by half the amount in layer space (5 - 2/2)
4159 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4160 gfx::Vector2d(0, 4)));
4163 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
4164 // When we try to scroll a non-scrollable child layer, the scroll delta
4165 // should be applied to one of its ancestors if possible.
4166 gfx::Size
surface_size(10, 10);
4167 gfx::Size
content_size(20, 20);
4168 scoped_ptr
<LayerImpl
> root_clip
=
4169 LayerImpl::Create(host_impl_
->active_tree(), 3);
4170 root_clip
->SetHasRenderSurface(true);
4171 scoped_ptr
<LayerImpl
> root
=
4172 CreateScrollableLayer(1, content_size
, root_clip
.get());
4173 // Make 'root' the clip layer for child: since they have the same sizes the
4174 // child will have zero max_scroll_offset and scrolls will bubble.
4175 scoped_ptr
<LayerImpl
> child
=
4176 CreateScrollableLayer(2, content_size
, root
.get());
4177 child
->SetIsContainerForFixedPositionLayers(true);
4178 root
->SetBounds(content_size
);
4180 int root_scroll_id
= root
->id();
4181 root
->AddChild(child
.Pass());
4182 root_clip
->AddChild(root
.Pass());
4184 host_impl_
->SetViewportSize(surface_size
);
4185 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4186 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
4188 host_impl_
->active_tree()->DidBecomeActive();
4191 gfx::Vector2d
scroll_delta(0, 4);
4192 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4193 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4194 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4195 host_impl_
->ScrollEnd();
4197 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4198 host_impl_
->ProcessScrollDeltas();
4200 // Only the root scroll should have scrolled.
4201 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
4203 ScrollInfoContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
));
4207 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
4208 gfx::Size
surface_size(10, 10);
4209 scoped_ptr
<LayerImpl
> root_clip
=
4210 LayerImpl::Create(host_impl_
->active_tree(), 1);
4211 scoped_ptr
<LayerImpl
> root_scroll
=
4212 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4213 root_scroll
->SetIsContainerForFixedPositionLayers(true);
4214 root_clip
->SetHasRenderSurface(true);
4215 root_clip
->AddChild(root_scroll
.Pass());
4216 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4217 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4219 host_impl_
->active_tree()->DidBecomeActive();
4220 host_impl_
->SetViewportSize(surface_size
);
4222 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4225 host_impl_
->active_tree()->DetachLayerTree();
4226 scoped_ptr
<LayerImpl
> root_clip2
=
4227 LayerImpl::Create(host_impl_
->active_tree(), 3);
4228 scoped_ptr
<LayerImpl
> root_scroll2
=
4229 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
4230 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
4231 root_clip2
->AddChild(root_scroll2
.Pass());
4232 root_clip2
->SetHasRenderSurface(true);
4233 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
4234 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
4236 host_impl_
->active_tree()->DidBecomeActive();
4238 // Scrolling should still work even though we did not draw yet.
4239 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4240 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4243 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
4244 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4246 // Rotate the root layer 90 degrees counter-clockwise about its center.
4247 gfx::Transform rotate_transform
;
4248 rotate_transform
.Rotate(-90.0);
4249 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
4251 gfx::Size
surface_size(50, 50);
4252 host_impl_
->SetViewportSize(surface_size
);
4255 // Scroll to the right in screen coordinates with a gesture.
4256 gfx::Vector2d
gesture_scroll_delta(10, 0);
4257 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4258 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4259 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4260 host_impl_
->ScrollEnd();
4262 // The layer should have scrolled down in its local coordinates.
4263 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4264 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4265 gfx::Vector2d(0, gesture_scroll_delta
.x())));
4267 // Reset and scroll down with the wheel.
4268 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4269 gfx::Vector2d
wheel_scroll_delta(0, 10);
4270 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4271 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4272 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4273 host_impl_
->ScrollEnd();
4275 // The layer should have scrolled down in its local coordinates.
4276 scroll_info
= host_impl_
->ProcessScrollDeltas();
4277 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4278 wheel_scroll_delta
));
4281 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
4282 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4283 int child_clip_layer_id
= 6;
4284 int child_layer_id
= 7;
4285 float child_layer_angle
= -20.f
;
4287 // Create a child layer that is rotated to a non-axis-aligned angle.
4288 scoped_ptr
<LayerImpl
> clip_layer
=
4289 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4290 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4291 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4292 gfx::Transform rotate_transform
;
4293 rotate_transform
.Translate(-50.0, -50.0);
4294 rotate_transform
.Rotate(child_layer_angle
);
4295 rotate_transform
.Translate(50.0, 50.0);
4296 clip_layer
->SetTransform(rotate_transform
);
4298 // Only allow vertical scrolling.
4299 clip_layer
->SetBounds(
4300 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
4301 // The rotation depends on the layer's transform origin, and the child layer
4302 // is a different size than the clip, so make sure the clip layer's origin
4303 // lines up over the child.
4304 clip_layer
->SetTransformOrigin(gfx::Point3F(
4305 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
4306 LayerImpl
* child_ptr
= child
.get();
4307 clip_layer
->AddChild(child
.Pass());
4308 scroll_layer
->AddChild(clip_layer
.Pass());
4310 gfx::Size
surface_size(50, 50);
4311 host_impl_
->SetViewportSize(surface_size
);
4314 // Scroll down in screen coordinates with a gesture.
4315 gfx::Vector2d
gesture_scroll_delta(0, 10);
4316 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4317 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4318 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4319 host_impl_
->ScrollEnd();
4321 // The child layer should have scrolled down in its local coordinates an
4322 // amount proportional to the angle between it and the input scroll delta.
4323 gfx::Vector2d
expected_scroll_delta(
4324 0, gesture_scroll_delta
.y() *
4325 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
4326 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4327 host_impl_
->ProcessScrollDeltas();
4328 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4329 expected_scroll_delta
));
4331 // The root scroll layer should not have scrolled, because the input delta
4332 // was close to the layer's axis of movement.
4333 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4336 // Now reset and scroll the same amount horizontally.
4337 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4338 gfx::Vector2d
gesture_scroll_delta(10, 0);
4339 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4340 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4341 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4342 host_impl_
->ScrollEnd();
4344 // The child layer should have scrolled down in its local coordinates an
4345 // amount proportional to the angle between it and the input scroll delta.
4346 gfx::Vector2d
expected_scroll_delta(
4347 0, -gesture_scroll_delta
.x() *
4348 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
4349 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4350 host_impl_
->ProcessScrollDeltas();
4351 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4352 expected_scroll_delta
));
4354 // The root scroll layer should have scrolled more, since the input scroll
4355 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4356 gfx::Vector2d
expected_root_scroll_delta(
4357 gesture_scroll_delta
.x() *
4358 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
4360 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4361 expected_root_scroll_delta
));
4365 TEST_F(LayerTreeHostImplTest
, ScrollPerspectiveTransformedLayer
) {
4366 // When scrolling an element with perspective, the distance scrolled
4367 // depends on the point at which the scroll begins.
4368 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4369 int child_clip_layer_id
= 6;
4370 int child_layer_id
= 7;
4372 // Create a child layer that is rotated on its x axis, with perspective.
4373 scoped_ptr
<LayerImpl
> clip_layer
=
4374 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4375 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4376 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4377 LayerImpl
* child_ptr
= child
.get();
4378 gfx::Transform perspective_transform
;
4379 perspective_transform
.Translate(-50.0, -50.0);
4380 perspective_transform
.ApplyPerspectiveDepth(20);
4381 perspective_transform
.RotateAboutXAxis(45);
4382 perspective_transform
.Translate(50.0, 50.0);
4383 clip_layer
->SetTransform(perspective_transform
);
4385 clip_layer
->SetBounds(gfx::Size(child_ptr
->bounds().width() / 2,
4386 child_ptr
->bounds().height() / 2));
4387 // The transform depends on the layer's transform origin, and the child layer
4388 // is a different size than the clip, so make sure the clip layer's origin
4389 // lines up over the child.
4390 clip_layer
->SetTransformOrigin(gfx::Point3F(
4391 clip_layer
->bounds().width(), clip_layer
->bounds().height(), 0.f
));
4392 clip_layer
->AddChild(child
.Pass());
4393 scroll_layer
->AddChild(clip_layer
.Pass());
4395 gfx::Size
surface_size(50, 50);
4396 host_impl_
->SetViewportSize(surface_size
);
4398 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
4400 gfx::Vector2d gesture_scroll_deltas
[4];
4401 gesture_scroll_deltas
[0] = gfx::Vector2d(4, 10);
4402 gesture_scroll_deltas
[1] = gfx::Vector2d(4, 10);
4403 gesture_scroll_deltas
[2] = gfx::Vector2d(10, 0);
4404 gesture_scroll_deltas
[3] = gfx::Vector2d(10, 0);
4406 gfx::Vector2d expected_scroll_deltas
[4];
4407 // Perspective affects the vertical delta by a different
4408 // amount depending on the vertical position of the |viewport_point|.
4409 expected_scroll_deltas
[0] = gfx::Vector2d(2, 8);
4410 expected_scroll_deltas
[1] = gfx::Vector2d(1, 4);
4411 // Deltas which start with the same vertical position of the
4412 // |viewport_point| are subject to identical perspective effects.
4413 expected_scroll_deltas
[2] = gfx::Vector2d(4, 0);
4414 expected_scroll_deltas
[3] = gfx::Vector2d(4, 0);
4416 gfx::Point
viewport_point(1, 1);
4418 // Scroll in screen coordinates with a gesture. Each scroll starts
4419 // where the previous scroll ended, but the scroll position is reset
4421 for (int i
= 0; i
< 4; ++i
) {
4422 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4424 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4425 host_impl_
->ScrollBegin(viewport_point
, InputHandler::GESTURE
));
4426 host_impl_
->ScrollBy(viewport_point
, gesture_scroll_deltas
[i
]);
4427 viewport_point
+= gesture_scroll_deltas
[i
];
4428 host_impl_
->ScrollEnd();
4430 scroll_info
= host_impl_
->ProcessScrollDeltas();
4431 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4432 expected_scroll_deltas
[i
]));
4434 // The root scroll layer should not have scrolled, because the input delta
4435 // was close to the layer's axis of movement.
4436 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4440 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
4441 LayerImpl
* scroll_layer
=
4442 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4444 // Scale the layer to twice its normal size.
4446 gfx::Transform scale_transform
;
4447 scale_transform
.Scale(scale
, scale
);
4448 scroll_layer
->SetTransform(scale_transform
);
4450 gfx::Size
surface_size(50, 50);
4451 host_impl_
->SetViewportSize(surface_size
);
4454 // Scroll down in screen coordinates with a gesture.
4455 gfx::Vector2d
scroll_delta(0, 10);
4456 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4457 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4458 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4459 host_impl_
->ScrollEnd();
4461 // The layer should have scrolled down in its local coordinates, but half the
4463 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4464 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4465 gfx::Vector2d(0, scroll_delta
.y() / scale
)));
4467 // Reset and scroll down with the wheel.
4468 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4469 gfx::Vector2d
wheel_scroll_delta(0, 10);
4470 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4471 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4472 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4473 host_impl_
->ScrollEnd();
4475 // It should apply the scale factor to the scroll delta for the wheel event.
4476 scroll_info
= host_impl_
->ProcessScrollDeltas();
4477 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4478 wheel_scroll_delta
));
4481 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
4485 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
4486 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
4487 gfx::Size(width
* scale
- 1, height
* scale
));
4488 host_impl_
->SetDeviceScaleFactor(scale
);
4489 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4491 LayerImpl
* inner_viewport_scroll_layer
=
4492 host_impl_
->active_tree()->InnerViewportScrollLayer();
4493 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4494 inner_viewport_scroll_layer
->MaxScrollOffset());
4497 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
4499 TestScrollOffsetDelegate()
4500 : page_scale_factor_(0.f
),
4501 min_page_scale_factor_(-1.f
),
4502 max_page_scale_factor_(-1.f
),
4503 needs_animate_(false) {}
4505 ~TestScrollOffsetDelegate() override
{}
4507 gfx::ScrollOffset
GetTotalScrollOffset() override
{
4508 return getter_return_value_
;
4511 void SetNeedsAnimate(const AnimationCallback
&) override
{
4512 needs_animate_
= true;
4515 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
4516 const gfx::ScrollOffset
& max_scroll_offset
,
4517 const gfx::SizeF
& scrollable_size
,
4518 float page_scale_factor
,
4519 float min_page_scale_factor
,
4520 float max_page_scale_factor
) override
{
4521 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
4522 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
4523 last_set_scroll_offset_
= total_scroll_offset
;
4524 max_scroll_offset_
= max_scroll_offset
;
4525 scrollable_size_
= scrollable_size
;
4526 page_scale_factor_
= page_scale_factor
;
4527 min_page_scale_factor_
= min_page_scale_factor
;
4528 max_page_scale_factor_
= max_page_scale_factor
;
4530 set_getter_return_value(last_set_scroll_offset_
);
4533 bool GetAndResetNeedsAnimate() {
4534 bool needs_animate
= needs_animate_
;
4535 needs_animate_
= false;
4536 return needs_animate
;
4539 gfx::ScrollOffset
last_set_scroll_offset() {
4540 return last_set_scroll_offset_
;
4543 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
4544 getter_return_value_
= value
;
4547 gfx::ScrollOffset
max_scroll_offset() const {
4548 return max_scroll_offset_
;
4551 gfx::SizeF
scrollable_size() const {
4552 return scrollable_size_
;
4555 float page_scale_factor() const {
4556 return page_scale_factor_
;
4559 float min_page_scale_factor() const {
4560 return min_page_scale_factor_
;
4563 float max_page_scale_factor() const {
4564 return max_page_scale_factor_
;
4568 gfx::ScrollOffset last_set_scroll_offset_
;
4569 gfx::ScrollOffset getter_return_value_
;
4570 gfx::ScrollOffset max_scroll_offset_
;
4571 gfx::SizeF scrollable_size_
;
4572 float page_scale_factor_
;
4573 float min_page_scale_factor_
;
4574 float max_page_scale_factor_
;
4575 bool needs_animate_
;
4578 // TODO(jdduke): Test root fling animation.
4579 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4580 TestScrollOffsetDelegate scroll_delegate
;
4581 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4582 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4583 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4584 clip_layer
->SetBounds(gfx::Size(10, 20));
4586 // Setting the delegate results in the current scroll offset being set.
4587 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4588 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4589 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4590 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4591 EXPECT_EQ(initial_scroll_delta
.ToString(),
4592 scroll_delegate
.last_set_scroll_offset().ToString());
4594 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4595 // page_scale_factor and {min|max}_page_scale_factor being set.
4596 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4597 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4598 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4599 EXPECT_EQ(1.f
, scroll_delegate
.min_page_scale_factor());
4600 EXPECT_EQ(1.f
, scroll_delegate
.max_page_scale_factor());
4602 // Updating page scale immediately updates the delegate.
4603 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4604 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4605 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4606 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4607 host_impl_
->SetPageScaleOnActiveTree(2.f
* 1.5f
);
4608 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
4609 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4610 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4611 host_impl_
->SetPageScaleOnActiveTree(2.f
);
4612 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4613 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4614 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4615 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4617 // The pinch gesture doesn't put the delegate into a state where the scroll
4618 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4620 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4621 host_impl_
->PinchGestureBegin();
4622 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4623 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4624 host_impl_
->PinchGestureEnd();
4625 host_impl_
->ScrollEnd();
4627 // Scrolling should be relative to the offset as returned by the delegate.
4628 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4629 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4631 scroll_delegate
.set_getter_return_value(current_offset
);
4632 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4633 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4634 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4636 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4637 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4638 scroll_delegate
.last_set_scroll_offset());
4640 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4641 scroll_delegate
.set_getter_return_value(current_offset
);
4642 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4643 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4644 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4645 scroll_delegate
.last_set_scroll_offset());
4646 host_impl_
->ScrollEnd();
4647 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
4648 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4650 // Forces a full tree synchronization and ensures that the scroll delegate
4651 // sees the correct size of the new tree.
4652 gfx::Size
new_size(42, 24);
4653 host_impl_
->CreatePendingTree();
4654 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
4655 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4656 host_impl_
->ActivateSyncTree();
4657 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4659 // Un-setting the delegate should propagate the delegate's current offset to
4660 // the root scrollable layer.
4661 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4662 scroll_delegate
.set_getter_return_value(current_offset
);
4663 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4664 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4666 EXPECT_EQ(current_offset
.ToString(),
4667 scroll_layer
->CurrentScrollOffset().ToString());
4670 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4671 const gfx::Transform target_space_transform
=
4672 layer
->draw_properties().target_space_transform
;
4673 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4674 gfx::Point translated_point
;
4675 target_space_transform
.TransformPoint(&translated_point
);
4676 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4677 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4680 TEST_F(LayerTreeHostImplTest
,
4681 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4682 TestScrollOffsetDelegate scroll_delegate
;
4683 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4684 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4685 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4686 clip_layer
->SetBounds(gfx::Size(10, 20));
4687 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4689 // Draw first frame to clear any pending draws and check scroll.
4691 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4692 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4694 // Set external scroll delta on delegate and notify LayerTreeHost.
4695 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4696 scroll_delegate
.set_getter_return_value(scroll_offset
);
4697 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4699 // Check scroll delta reflected in layer.
4700 LayerTreeHostImpl::FrameData frame
;
4701 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4702 host_impl_
->DrawLayers(&frame
);
4703 host_impl_
->DidDrawAllLayers(frame
);
4704 EXPECT_FALSE(frame
.has_no_damage
);
4705 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4707 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4710 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4711 InputHandlerScrollResult scroll_result
;
4712 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4713 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4714 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4716 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4718 // In-bounds scrolling does not affect overscroll.
4719 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4720 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4721 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4722 EXPECT_TRUE(scroll_result
.did_scroll
);
4723 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4724 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4725 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4727 // Overscroll events are reflected immediately.
4728 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4729 EXPECT_TRUE(scroll_result
.did_scroll
);
4730 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4731 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4732 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4733 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4734 host_impl_
->accumulated_root_overscroll());
4736 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4737 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4738 EXPECT_TRUE(scroll_result
.did_scroll
);
4739 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4740 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4741 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4742 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4743 host_impl_
->accumulated_root_overscroll());
4745 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4746 EXPECT_FALSE(scroll_result
.did_scroll
);
4747 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4748 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4749 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4750 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4751 host_impl_
->accumulated_root_overscroll());
4753 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4754 EXPECT_TRUE(scroll_result
.did_scroll
);
4755 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4756 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4757 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4758 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4759 host_impl_
->accumulated_root_overscroll());
4761 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4762 EXPECT_TRUE(scroll_result
.did_scroll
);
4763 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4764 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4765 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4766 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4767 host_impl_
->accumulated_root_overscroll());
4769 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4770 EXPECT_TRUE(scroll_result
.did_scroll
);
4771 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4772 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4773 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4774 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4775 host_impl_
->accumulated_root_overscroll());
4777 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4778 EXPECT_TRUE(scroll_result
.did_scroll
);
4779 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4780 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4781 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4782 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4783 host_impl_
->accumulated_root_overscroll());
4785 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4786 // as no scroll occurs.
4787 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4788 EXPECT_FALSE(scroll_result
.did_scroll
);
4789 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4790 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4791 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4792 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4793 host_impl_
->accumulated_root_overscroll());
4795 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4796 EXPECT_FALSE(scroll_result
.did_scroll
);
4797 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4798 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4799 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4800 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4801 host_impl_
->accumulated_root_overscroll());
4803 // Overscroll resets on valid scroll.
4804 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4805 EXPECT_TRUE(scroll_result
.did_scroll
);
4806 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4807 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4808 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4809 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4810 host_impl_
->accumulated_root_overscroll());
4812 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4813 EXPECT_TRUE(scroll_result
.did_scroll
);
4814 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4815 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4816 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4817 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4818 host_impl_
->accumulated_root_overscroll());
4820 host_impl_
->ScrollEnd();
4824 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4825 // Scroll child layers beyond their maximum scroll range and make sure root
4826 // overscroll does not accumulate.
4827 InputHandlerScrollResult scroll_result
;
4828 gfx::Size
surface_size(10, 10);
4829 scoped_ptr
<LayerImpl
> root_clip
=
4830 LayerImpl::Create(host_impl_
->active_tree(), 4);
4831 root_clip
->SetHasRenderSurface(true);
4833 scoped_ptr
<LayerImpl
> root
=
4834 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4836 scoped_ptr
<LayerImpl
> grand_child
=
4837 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4839 scoped_ptr
<LayerImpl
> child
=
4840 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4841 LayerImpl
* grand_child_layer
= grand_child
.get();
4842 child
->AddChild(grand_child
.Pass());
4844 LayerImpl
* child_layer
= child
.get();
4845 root
->AddChild(child
.Pass());
4846 root_clip
->AddChild(root
.Pass());
4847 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4848 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4849 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4850 host_impl_
->active_tree()->DidBecomeActive();
4851 host_impl_
->SetViewportSize(surface_size
);
4854 gfx::Vector2d
scroll_delta(0, -10);
4855 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4856 host_impl_
->ScrollBegin(gfx::Point(),
4857 InputHandler::NON_BUBBLING_GESTURE
));
4858 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4859 EXPECT_TRUE(scroll_result
.did_scroll
);
4860 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4861 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4862 host_impl_
->ScrollEnd();
4864 // The next time we scroll we should only scroll the parent, but overscroll
4865 // should still not reach the root layer.
4866 scroll_delta
= gfx::Vector2d(0, -30);
4867 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4868 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4869 InputHandler::NON_BUBBLING_GESTURE
));
4870 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4871 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4872 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4873 EXPECT_TRUE(scroll_result
.did_scroll
);
4874 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4875 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4876 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4877 host_impl_
->ScrollEnd();
4879 // After scrolling the parent, another scroll on the opposite direction
4880 // should scroll the child.
4881 scroll_delta
= gfx::Vector2d(0, 70);
4882 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4883 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4884 InputHandler::NON_BUBBLING_GESTURE
));
4885 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4886 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4887 EXPECT_TRUE(scroll_result
.did_scroll
);
4888 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4889 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4890 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4891 host_impl_
->ScrollEnd();
4895 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4896 // When we try to scroll a non-scrollable child layer, the scroll delta
4897 // should be applied to one of its ancestors if possible. Overscroll should
4898 // be reflected only when it has bubbled up to the root scrolling layer.
4899 InputHandlerScrollResult scroll_result
;
4900 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4903 gfx::Vector2d
scroll_delta(0, 8);
4904 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4905 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4906 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4907 EXPECT_TRUE(scroll_result
.did_scroll
);
4908 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4909 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4910 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4911 EXPECT_TRUE(scroll_result
.did_scroll
);
4912 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4913 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4914 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4915 EXPECT_FALSE(scroll_result
.did_scroll
);
4916 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4917 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4918 host_impl_
->ScrollEnd();
4922 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4923 InputHandlerScrollResult scroll_result
;
4924 LayerTreeSettings settings
;
4925 CreateHostImpl(settings
, CreateOutputSurface());
4927 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4928 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4929 clip_layer
->SetBounds(gfx::Size(50, 50));
4930 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4931 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4933 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4935 // Even though the layer can't scroll the overscroll still happens.
4936 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4937 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4938 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4939 EXPECT_FALSE(scroll_result
.did_scroll
);
4940 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4941 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4944 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4945 InputHandlerScrollResult scroll_result
;
4946 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4950 // Edge glow effect should be applicable only upon reaching Edges
4951 // of the content. unnecessary glow effect calls shouldn't be
4952 // called while scrolling up without reaching the edge of the content.
4953 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4954 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4955 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4956 EXPECT_TRUE(scroll_result
.did_scroll
);
4957 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4958 EXPECT_EQ(gfx::Vector2dF().ToString(),
4959 host_impl_
->accumulated_root_overscroll().ToString());
4961 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4962 EXPECT_TRUE(scroll_result
.did_scroll
);
4963 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4964 EXPECT_EQ(gfx::Vector2dF().ToString(),
4965 host_impl_
->accumulated_root_overscroll().ToString());
4966 host_impl_
->ScrollEnd();
4967 // unusedrootDelta should be subtracted from applied delta so that
4968 // unwanted glow effect calls are not called.
4969 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4970 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4971 InputHandler::NON_BUBBLING_GESTURE
));
4972 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4973 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4974 EXPECT_TRUE(scroll_result
.did_scroll
);
4975 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4976 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4977 host_impl_
->accumulated_root_overscroll().ToString());
4980 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4981 EXPECT_FALSE(scroll_result
.did_scroll
);
4982 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4983 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4984 host_impl_
->accumulated_root_overscroll().ToString());
4985 host_impl_
->ScrollEnd();
4986 // TestCase to check kEpsilon, which prevents minute values to trigger
4987 // gloweffect without reaching edge.
4988 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4989 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4991 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4992 EXPECT_FALSE(scroll_result
.did_scroll
);
4993 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4994 EXPECT_EQ(gfx::Vector2dF().ToString(),
4995 host_impl_
->accumulated_root_overscroll().ToString());
4996 host_impl_
->ScrollEnd();
5000 class BlendStateCheckLayer
: public LayerImpl
{
5002 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
5004 ResourceProvider
* resource_provider
) {
5005 return make_scoped_ptr(
5006 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
5009 void AppendQuads(RenderPass
* render_pass
,
5010 AppendQuadsData
* append_quads_data
) override
{
5011 quads_appended_
= true;
5013 gfx::Rect opaque_rect
;
5014 if (contents_opaque())
5015 opaque_rect
= quad_rect_
;
5017 opaque_rect
= opaque_content_rect_
;
5018 gfx::Rect visible_quad_rect
= quad_rect_
;
5020 SharedQuadState
* shared_quad_state
=
5021 render_pass
->CreateAndAppendSharedQuadState();
5022 PopulateSharedQuadState(shared_quad_state
);
5024 TileDrawQuad
* test_blending_draw_quad
=
5025 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
5026 test_blending_draw_quad
->SetNew(shared_quad_state
,
5031 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
5035 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
5036 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
5037 EXPECT_EQ(has_render_surface_
, !!render_surface());
5040 void SetExpectation(bool blend
, bool has_render_surface
) {
5042 has_render_surface_
= has_render_surface
;
5043 quads_appended_
= false;
5046 bool quads_appended() const { return quads_appended_
; }
5048 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
5049 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
5050 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
5051 opaque_content_rect_
= rect
;
5055 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
5057 ResourceProvider
* resource_provider
)
5058 : LayerImpl(tree_impl
, id
),
5060 has_render_surface_(false),
5061 quads_appended_(false),
5062 quad_rect_(5, 5, 5, 5),
5063 quad_visible_rect_(5, 5, 5, 5),
5064 resource_id_(resource_provider
->CreateResource(
5067 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
5069 resource_provider
->AllocateForTesting(resource_id_
);
5070 SetBounds(gfx::Size(10, 10));
5071 SetDrawsContent(true);
5075 bool has_render_surface_
;
5076 bool quads_appended_
;
5077 gfx::Rect quad_rect_
;
5078 gfx::Rect opaque_content_rect_
;
5079 gfx::Rect quad_visible_rect_
;
5080 ResourceId resource_id_
;
5083 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
5085 scoped_ptr
<LayerImpl
> root
=
5086 LayerImpl::Create(host_impl_
->active_tree(), 1);
5087 root
->SetBounds(gfx::Size(10, 10));
5088 root
->SetDrawsContent(false);
5089 root
->SetHasRenderSurface(true);
5090 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5092 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5095 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5097 host_impl_
->resource_provider()));
5098 BlendStateCheckLayer
* layer1
=
5099 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
5100 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
5102 LayerTreeHostImpl::FrameData frame
;
5104 // Opaque layer, drawn without blending.
5105 layer1
->SetContentsOpaque(true);
5106 layer1
->SetExpectation(false, false);
5107 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5108 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5109 host_impl_
->DrawLayers(&frame
);
5110 EXPECT_TRUE(layer1
->quads_appended());
5111 host_impl_
->DidDrawAllLayers(frame
);
5113 // Layer with translucent content and painting, so drawn with blending.
5114 layer1
->SetContentsOpaque(false);
5115 layer1
->SetExpectation(true, false);
5116 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5117 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5118 host_impl_
->DrawLayers(&frame
);
5119 EXPECT_TRUE(layer1
->quads_appended());
5120 host_impl_
->DidDrawAllLayers(frame
);
5122 // Layer with translucent opacity, drawn with blending.
5123 layer1
->SetContentsOpaque(true);
5124 layer1
->SetOpacity(0.5f
);
5125 layer1
->SetExpectation(true, false);
5126 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5127 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5128 host_impl_
->DrawLayers(&frame
);
5129 EXPECT_TRUE(layer1
->quads_appended());
5130 host_impl_
->DidDrawAllLayers(frame
);
5132 // Layer with translucent opacity and painting, drawn with blending.
5133 layer1
->SetContentsOpaque(true);
5134 layer1
->SetOpacity(0.5f
);
5135 layer1
->SetExpectation(true, false);
5136 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5137 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5138 host_impl_
->DrawLayers(&frame
);
5139 EXPECT_TRUE(layer1
->quads_appended());
5140 host_impl_
->DidDrawAllLayers(frame
);
5143 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5145 host_impl_
->resource_provider()));
5146 BlendStateCheckLayer
* layer2
=
5147 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
5148 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
5150 // 2 opaque layers, drawn without blending.
5151 layer1
->SetContentsOpaque(true);
5152 layer1
->SetOpacity(1.f
);
5153 layer1
->SetExpectation(false, false);
5154 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5155 layer2
->SetContentsOpaque(true);
5156 layer2
->SetOpacity(1.f
);
5157 layer2
->SetExpectation(false, false);
5158 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5159 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5160 host_impl_
->DrawLayers(&frame
);
5161 EXPECT_TRUE(layer1
->quads_appended());
5162 EXPECT_TRUE(layer2
->quads_appended());
5163 host_impl_
->DidDrawAllLayers(frame
);
5165 // Parent layer with translucent content, drawn with blending.
5166 // Child layer with opaque content, drawn without blending.
5167 layer1
->SetContentsOpaque(false);
5168 layer1
->SetExpectation(true, false);
5169 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5170 layer2
->SetExpectation(false, false);
5171 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5172 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5173 host_impl_
->DrawLayers(&frame
);
5174 EXPECT_TRUE(layer1
->quads_appended());
5175 EXPECT_TRUE(layer2
->quads_appended());
5176 host_impl_
->DidDrawAllLayers(frame
);
5178 // Parent layer with translucent content but opaque painting, drawn without
5180 // Child layer with opaque content, drawn without blending.
5181 layer1
->SetContentsOpaque(true);
5182 layer1
->SetExpectation(false, false);
5183 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5184 layer2
->SetExpectation(false, false);
5185 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5186 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5187 host_impl_
->DrawLayers(&frame
);
5188 EXPECT_TRUE(layer1
->quads_appended());
5189 EXPECT_TRUE(layer2
->quads_appended());
5190 host_impl_
->DidDrawAllLayers(frame
);
5192 // Parent layer with translucent opacity and opaque content. Since it has a
5193 // drawing child, it's drawn to a render surface which carries the opacity,
5194 // so it's itself drawn without blending.
5195 // Child layer with opaque content, drawn without blending (parent surface
5196 // carries the inherited opacity).
5197 layer1
->SetContentsOpaque(true);
5198 layer1
->SetOpacity(0.5f
);
5199 layer1
->SetHasRenderSurface(true);
5200 layer1
->SetExpectation(false, true);
5201 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5202 layer2
->SetExpectation(false, false);
5203 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5204 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5205 host_impl_
->active_tree()->root_layer());
5206 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5207 host_impl_
->DrawLayers(&frame
);
5208 EXPECT_TRUE(layer1
->quads_appended());
5209 EXPECT_TRUE(layer2
->quads_appended());
5210 host_impl_
->DidDrawAllLayers(frame
);
5211 layer1
->SetHasRenderSurface(false);
5213 // Draw again, but with child non-opaque, to make sure
5214 // layer1 not culled.
5215 layer1
->SetContentsOpaque(true);
5216 layer1
->SetOpacity(1.f
);
5217 layer1
->SetExpectation(false, false);
5218 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5219 layer2
->SetContentsOpaque(true);
5220 layer2
->SetOpacity(0.5f
);
5221 layer2
->SetExpectation(true, false);
5222 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5223 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5224 host_impl_
->DrawLayers(&frame
);
5225 EXPECT_TRUE(layer1
->quads_appended());
5226 EXPECT_TRUE(layer2
->quads_appended());
5227 host_impl_
->DidDrawAllLayers(frame
);
5229 // A second way of making the child non-opaque.
5230 layer1
->SetContentsOpaque(true);
5231 layer1
->SetOpacity(1.f
);
5232 layer1
->SetExpectation(false, false);
5233 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5234 layer2
->SetContentsOpaque(false);
5235 layer2
->SetOpacity(1.f
);
5236 layer2
->SetExpectation(true, false);
5237 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5238 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5239 host_impl_
->DrawLayers(&frame
);
5240 EXPECT_TRUE(layer1
->quads_appended());
5241 EXPECT_TRUE(layer2
->quads_appended());
5242 host_impl_
->DidDrawAllLayers(frame
);
5244 // And when the layer says its not opaque but is painted opaque, it is not
5246 layer1
->SetContentsOpaque(true);
5247 layer1
->SetOpacity(1.f
);
5248 layer1
->SetExpectation(false, false);
5249 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5250 layer2
->SetContentsOpaque(true);
5251 layer2
->SetOpacity(1.f
);
5252 layer2
->SetExpectation(false, false);
5253 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5254 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5255 host_impl_
->DrawLayers(&frame
);
5256 EXPECT_TRUE(layer1
->quads_appended());
5257 EXPECT_TRUE(layer2
->quads_appended());
5258 host_impl_
->DidDrawAllLayers(frame
);
5260 // Layer with partially opaque contents, drawn with blending.
5261 layer1
->SetContentsOpaque(false);
5262 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5263 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5264 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5265 layer1
->SetExpectation(true, false);
5266 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5267 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5268 host_impl_
->DrawLayers(&frame
);
5269 EXPECT_TRUE(layer1
->quads_appended());
5270 host_impl_
->DidDrawAllLayers(frame
);
5272 // Layer with partially opaque contents partially culled, drawn with blending.
5273 layer1
->SetContentsOpaque(false);
5274 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5275 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5276 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5277 layer1
->SetExpectation(true, false);
5278 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5279 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5280 host_impl_
->DrawLayers(&frame
);
5281 EXPECT_TRUE(layer1
->quads_appended());
5282 host_impl_
->DidDrawAllLayers(frame
);
5284 // Layer with partially opaque contents culled, drawn with blending.
5285 layer1
->SetContentsOpaque(false);
5286 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5287 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5288 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5289 layer1
->SetExpectation(true, false);
5290 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5291 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5292 host_impl_
->DrawLayers(&frame
);
5293 EXPECT_TRUE(layer1
->quads_appended());
5294 host_impl_
->DidDrawAllLayers(frame
);
5296 // Layer with partially opaque contents and translucent contents culled, drawn
5297 // without blending.
5298 layer1
->SetContentsOpaque(false);
5299 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5300 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5301 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5302 layer1
->SetExpectation(false, false);
5303 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5304 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5305 host_impl_
->DrawLayers(&frame
);
5306 EXPECT_TRUE(layer1
->quads_appended());
5307 host_impl_
->DidDrawAllLayers(frame
);
5310 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
5312 LayerTreeHostImplViewportCoveredTest() :
5313 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
5315 did_activate_pending_tree_(false) {}
5317 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
5319 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5321 return FakeOutputSurface::Create3d();
5324 void SetupActiveTreeLayers() {
5325 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
5326 host_impl_
->active_tree()->SetRootLayer(
5327 LayerImpl::Create(host_impl_
->active_tree(), 1));
5328 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
5329 host_impl_
->active_tree()->root_layer()->AddChild(
5330 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5332 host_impl_
->resource_provider()));
5333 child_
= static_cast<BlendStateCheckLayer
*>(
5334 host_impl_
->active_tree()->root_layer()->children()[0]);
5335 child_
->SetExpectation(false, false);
5336 child_
->SetContentsOpaque(true);
5339 // Expect no gutter rects.
5340 void TestLayerCoversFullViewport() {
5341 gfx::Rect
layer_rect(viewport_size_
);
5342 child_
->SetPosition(layer_rect
.origin());
5343 child_
->SetBounds(layer_rect
.size());
5344 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5345 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5347 LayerTreeHostImpl::FrameData frame
;
5348 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5349 ASSERT_EQ(1u, frame
.render_passes
.size());
5351 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5352 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5353 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5355 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5356 host_impl_
->DidDrawAllLayers(frame
);
5359 // Expect fullscreen gutter rect.
5360 void TestEmptyLayer() {
5361 gfx::Rect
layer_rect(0, 0, 0, 0);
5362 child_
->SetPosition(layer_rect
.origin());
5363 child_
->SetBounds(layer_rect
.size());
5364 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5365 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5367 LayerTreeHostImpl::FrameData frame
;
5368 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5369 ASSERT_EQ(1u, frame
.render_passes
.size());
5371 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5372 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5373 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5375 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5376 host_impl_
->DidDrawAllLayers(frame
);
5379 // Expect four surrounding gutter rects.
5380 void TestLayerInMiddleOfViewport() {
5381 gfx::Rect
layer_rect(500, 500, 200, 200);
5382 child_
->SetPosition(layer_rect
.origin());
5383 child_
->SetBounds(layer_rect
.size());
5384 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5385 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5387 LayerTreeHostImpl::FrameData frame
;
5388 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5389 ASSERT_EQ(1u, frame
.render_passes
.size());
5391 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5392 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
5393 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5395 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5396 host_impl_
->DidDrawAllLayers(frame
);
5399 // Expect no gutter rects.
5400 void TestLayerIsLargerThanViewport() {
5401 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
5402 viewport_size_
.height() + 10);
5403 child_
->SetPosition(layer_rect
.origin());
5404 child_
->SetBounds(layer_rect
.size());
5405 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5406 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5408 LayerTreeHostImpl::FrameData frame
;
5409 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5410 ASSERT_EQ(1u, frame
.render_passes
.size());
5412 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5413 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5414 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5416 host_impl_
->DidDrawAllLayers(frame
);
5419 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
5421 void set_gutter_quad_material(DrawQuad::Material material
) {
5422 gutter_quad_material_
= material
;
5424 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
5425 gutter_texture_size_
= gutter_texture_size
;
5429 size_t CountGutterQuads(const QuadList
& quad_list
) {
5430 size_t num_gutter_quads
= 0;
5431 for (const auto& quad
: quad_list
) {
5432 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
5434 return num_gutter_quads
;
5437 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
5438 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5439 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
5442 // Make sure that the texture coordinates match their expectations.
5443 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
5444 for (const auto& quad
: quad_list
) {
5445 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
5447 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
5448 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
5449 gutter_texture_size_
, host_impl_
->device_scale_factor());
5450 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
5451 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
5452 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
5453 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
5455 texture_quad
->uv_bottom_right
.x(),
5456 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
5458 texture_quad
->uv_bottom_right
.y(),
5459 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
5463 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
5464 return gfx::ToRoundedSize(
5465 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
5468 DrawQuad::Material gutter_quad_material_
;
5469 gfx::Size gutter_texture_size_
;
5470 gfx::Size viewport_size_
;
5471 BlendStateCheckLayer
* child_
;
5472 bool did_activate_pending_tree_
;
5475 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
5476 viewport_size_
= gfx::Size(1000, 1000);
5478 bool always_draw
= false;
5479 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5481 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5482 SetupActiveTreeLayers();
5483 TestLayerCoversFullViewport();
5485 TestLayerInMiddleOfViewport();
5486 TestLayerIsLargerThanViewport();
5489 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
5490 viewport_size_
= gfx::Size(1000, 1000);
5492 bool always_draw
= false;
5493 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5495 host_impl_
->SetDeviceScaleFactor(2.f
);
5496 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5497 SetupActiveTreeLayers();
5498 TestLayerCoversFullViewport();
5500 TestLayerInMiddleOfViewport();
5501 TestLayerIsLargerThanViewport();
5504 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
5505 viewport_size_
= gfx::Size(1000, 1000);
5507 bool always_draw
= true;
5508 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5510 // Pending tree to force active_tree size invalid. Not used otherwise.
5511 host_impl_
->CreatePendingTree();
5512 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5513 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5515 SetupActiveTreeLayers();
5517 TestLayerInMiddleOfViewport();
5518 TestLayerIsLargerThanViewport();
5521 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5522 viewport_size_
= gfx::Size(1000, 1000);
5524 bool always_draw
= true;
5525 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5527 // Set larger viewport and activate it to active tree.
5528 host_impl_
->CreatePendingTree();
5529 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5530 viewport_size_
.height() + 100);
5531 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5532 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5533 host_impl_
->ActivateSyncTree();
5534 EXPECT_TRUE(did_activate_pending_tree_
);
5535 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5537 // Shrink pending tree viewport without activating.
5538 host_impl_
->CreatePendingTree();
5539 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5540 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5542 SetupActiveTreeLayers();
5544 TestLayerInMiddleOfViewport();
5545 TestLayerIsLargerThanViewport();
5548 class FakeDrawableLayerImpl
: public LayerImpl
{
5550 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5551 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5554 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5555 : LayerImpl(tree_impl
, id
) {}
5558 // Only reshape when we know we are going to draw. Otherwise, the reshape
5559 // can leave the window at the wrong size if we never draw and the proper
5560 // viewport size is never set.
5561 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5562 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5563 scoped_ptr
<OutputSurface
> output_surface(
5564 FakeOutputSurface::Create3d(provider
));
5565 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5567 scoped_ptr
<LayerImpl
> root
=
5568 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5569 root
->SetBounds(gfx::Size(10, 10));
5570 root
->SetDrawsContent(true);
5571 root
->SetHasRenderSurface(true);
5572 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5573 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5574 provider
->TestContext3d()->clear_reshape_called();
5576 LayerTreeHostImpl::FrameData frame
;
5577 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5578 host_impl_
->SetDeviceScaleFactor(1.f
);
5579 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5580 host_impl_
->DrawLayers(&frame
);
5581 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5582 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5583 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5584 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5585 host_impl_
->DidDrawAllLayers(frame
);
5586 provider
->TestContext3d()->clear_reshape_called();
5588 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5589 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5590 host_impl_
->DrawLayers(&frame
);
5591 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5592 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5593 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5594 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5595 host_impl_
->DidDrawAllLayers(frame
);
5596 provider
->TestContext3d()->clear_reshape_called();
5598 host_impl_
->SetDeviceScaleFactor(2.f
);
5599 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5600 host_impl_
->DrawLayers(&frame
);
5601 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5602 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5603 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5604 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5605 host_impl_
->DidDrawAllLayers(frame
);
5606 provider
->TestContext3d()->clear_reshape_called();
5609 // Make sure damage tracking propagates all the way to the graphics context,
5610 // where it should request to swap only the sub-buffer that is damaged.
5611 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5612 scoped_refptr
<TestContextProvider
> context_provider(
5613 TestContextProvider::Create());
5614 context_provider
->BindToCurrentThread();
5615 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5617 scoped_ptr
<FakeOutputSurface
> output_surface(
5618 FakeOutputSurface::Create3d(context_provider
));
5619 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5621 // This test creates its own LayerTreeHostImpl, so
5622 // that we can force partial swap enabled.
5623 LayerTreeSettings settings
;
5624 settings
.renderer_settings
.partial_swap_enabled
= true;
5625 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5626 LayerTreeHostImpl::Create(
5627 settings
, this, &proxy_
, &stats_instrumentation_
,
5628 &shared_bitmap_manager_
, NULL
, &task_graph_runner_
, 0);
5629 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5630 layer_tree_host_impl
->WillBeginImplFrame(
5631 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5632 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5634 scoped_ptr
<LayerImpl
> root
=
5635 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5636 root
->SetHasRenderSurface(true);
5637 scoped_ptr
<LayerImpl
> child
=
5638 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5639 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5640 child
->SetBounds(gfx::Size(14, 15));
5641 child
->SetDrawsContent(true);
5642 root
->SetBounds(gfx::Size(500, 500));
5643 root
->SetDrawsContent(true);
5644 root
->AddChild(child
.Pass());
5645 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5647 LayerTreeHostImpl::FrameData frame
;
5649 // First frame, the entire screen should get swapped.
5650 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5651 layer_tree_host_impl
->DrawLayers(&frame
);
5652 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5653 layer_tree_host_impl
->SwapBuffers(frame
);
5654 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5655 EXPECT_EQ(expected_swap_rect
.ToString(),
5656 fake_output_surface
->last_swap_rect().ToString());
5658 // Second frame, only the damaged area should get swapped. Damage should be
5659 // the union of old and new child rects.
5660 // expected damage rect: gfx::Rect(26, 28);
5661 // expected swap rect: vertically flipped, with origin at bottom left corner.
5662 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5664 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5665 layer_tree_host_impl
->DrawLayers(&frame
);
5666 host_impl_
->DidDrawAllLayers(frame
);
5667 layer_tree_host_impl
->SwapBuffers(frame
);
5669 // Make sure that partial swap is constrained to the viewport dimensions
5670 // expected damage rect: gfx::Rect(500, 500);
5671 // expected swap rect: flipped damage rect, but also clamped to viewport
5672 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5673 EXPECT_EQ(expected_swap_rect
.ToString(),
5674 fake_output_surface
->last_swap_rect().ToString());
5676 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5677 // This will damage everything.
5678 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5680 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5681 layer_tree_host_impl
->DrawLayers(&frame
);
5682 host_impl_
->DidDrawAllLayers(frame
);
5683 layer_tree_host_impl
->SwapBuffers(frame
);
5685 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5686 EXPECT_EQ(expected_swap_rect
.ToString(),
5687 fake_output_surface
->last_swap_rect().ToString());
5690 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5691 scoped_ptr
<LayerImpl
> root
=
5692 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5693 scoped_ptr
<LayerImpl
> child
=
5694 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5695 child
->SetBounds(gfx::Size(10, 10));
5696 child
->SetDrawsContent(true);
5697 root
->SetBounds(gfx::Size(10, 10));
5698 root
->SetDrawsContent(true);
5699 root
->SetHasRenderSurface(true);
5700 root
->AddChild(child
.Pass());
5702 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5704 LayerTreeHostImpl::FrameData frame
;
5706 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5707 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5708 EXPECT_EQ(1u, frame
.render_passes
.size());
5709 host_impl_
->DidDrawAllLayers(frame
);
5712 class FakeLayerWithQuads
: public LayerImpl
{
5714 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5715 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5718 void AppendQuads(RenderPass
* render_pass
,
5719 AppendQuadsData
* append_quads_data
) override
{
5720 SharedQuadState
* shared_quad_state
=
5721 render_pass
->CreateAndAppendSharedQuadState();
5722 PopulateSharedQuadState(shared_quad_state
);
5724 SkColor gray
= SkColorSetRGB(100, 100, 100);
5725 gfx::Rect
quad_rect(bounds());
5726 gfx::Rect
visible_quad_rect(quad_rect
);
5727 SolidColorDrawQuad
* my_quad
=
5728 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5730 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5734 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5735 : LayerImpl(tree_impl
, id
) {}
5738 class MockContext
: public TestWebGraphicsContext3D
{
5740 MOCK_METHOD1(useProgram
, void(GLuint program
));
5741 MOCK_METHOD5(uniform4f
, void(GLint location
,
5746 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5748 GLboolean transpose
,
5749 const GLfloat
* value
));
5750 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5754 MOCK_METHOD1(enable
, void(GLenum cap
));
5755 MOCK_METHOD1(disable
, void(GLenum cap
));
5756 MOCK_METHOD4(scissor
, void(GLint x
,
5762 class MockContextHarness
{
5764 MockContext
* context_
;
5767 explicit MockContextHarness(MockContext
* context
)
5768 : context_(context
) {
5769 context_
->set_have_post_sub_buffer(true);
5771 // Catch "uninteresting" calls
5772 EXPECT_CALL(*context_
, useProgram(_
))
5775 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5778 // These are not asserted
5779 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5780 .WillRepeatedly(Return());
5782 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5783 .WillRepeatedly(Return());
5785 // Any un-sanctioned calls to enable() are OK
5786 EXPECT_CALL(*context_
, enable(_
))
5787 .WillRepeatedly(Return());
5789 // Any un-sanctioned calls to disable() are OK
5790 EXPECT_CALL(*context_
, disable(_
))
5791 .WillRepeatedly(Return());
5794 void MustDrawSolidQuad() {
5795 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5797 .RetiresOnSaturation();
5799 EXPECT_CALL(*context_
, useProgram(_
))
5801 .RetiresOnSaturation();
5804 void MustSetScissor(int x
, int y
, int width
, int height
) {
5805 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5806 .WillRepeatedly(Return());
5808 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5810 .WillRepeatedly(Return());
5813 void MustSetNoScissor() {
5814 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5815 .WillRepeatedly(Return());
5817 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5820 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5825 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5826 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5827 MockContext
* mock_context
= mock_context_owned
.get();
5828 MockContextHarness
harness(mock_context
);
5831 LayerTreeSettings settings
= DefaultSettings();
5832 settings
.renderer_settings
.partial_swap_enabled
= false;
5833 CreateHostImpl(settings
,
5834 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5835 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5837 // Without partial swap, and no clipping, no scissor is set.
5838 harness
.MustDrawSolidQuad();
5839 harness
.MustSetNoScissor();
5841 LayerTreeHostImpl::FrameData frame
;
5842 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5843 host_impl_
->DrawLayers(&frame
);
5844 host_impl_
->DidDrawAllLayers(frame
);
5846 Mock::VerifyAndClearExpectations(&mock_context
);
5848 // Without partial swap, but a layer does clip its subtree, one scissor is
5850 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5851 harness
.MustDrawSolidQuad();
5852 harness
.MustSetScissor(0, 0, 10, 10);
5854 LayerTreeHostImpl::FrameData frame
;
5855 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
5856 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5857 host_impl_
->DrawLayers(&frame
);
5858 host_impl_
->DidDrawAllLayers(frame
);
5860 Mock::VerifyAndClearExpectations(&mock_context
);
5863 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5864 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5865 MockContext
* mock_context
= context_owned
.get();
5866 MockContextHarness
harness(mock_context
);
5868 LayerTreeSettings settings
= DefaultSettings();
5869 settings
.renderer_settings
.partial_swap_enabled
= true;
5870 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5871 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5873 // The first frame is not a partially-swapped one. No scissor should be set.
5874 harness
.MustSetNoScissor();
5875 harness
.MustDrawSolidQuad();
5877 LayerTreeHostImpl::FrameData frame
;
5878 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5879 host_impl_
->DrawLayers(&frame
);
5880 host_impl_
->DidDrawAllLayers(frame
);
5882 Mock::VerifyAndClearExpectations(&mock_context
);
5884 // Damage a portion of the frame.
5885 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5886 gfx::Rect(0, 0, 2, 3));
5888 // The second frame will be partially-swapped (the y coordinates are flipped).
5889 harness
.MustSetScissor(0, 7, 2, 3);
5890 harness
.MustDrawSolidQuad();
5892 LayerTreeHostImpl::FrameData frame
;
5893 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5894 host_impl_
->DrawLayers(&frame
);
5895 host_impl_
->DidDrawAllLayers(frame
);
5897 Mock::VerifyAndClearExpectations(&mock_context
);
5900 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5902 LayerTreeHostImplClient
* client
,
5904 SharedBitmapManager
* manager
,
5905 TaskGraphRunner
* task_graph_runner
,
5906 RenderingStatsInstrumentation
* stats_instrumentation
) {
5907 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5908 scoped_ptr
<OutputSurface
> output_surface(
5909 FakeOutputSurface::Create3d(provider
));
5910 provider
->BindToCurrentThread();
5911 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5913 LayerTreeSettings settings
;
5914 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5915 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5916 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
,
5917 manager
, nullptr, task_graph_runner
, 0);
5918 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5919 my_host_impl
->WillBeginImplFrame(
5920 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5921 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5924 Layers are created as follows:
5926 +--------------------+
5930 | | +-------------------+
5932 | | +-------------------+
5937 +--------------------+
5939 Layers 1, 2 have render surfaces
5941 scoped_ptr
<LayerImpl
> root
=
5942 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5943 scoped_ptr
<LayerImpl
> child
=
5944 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5945 scoped_ptr
<LayerImpl
> grand_child
=
5946 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5948 gfx::Rect
root_rect(0, 0, 100, 100);
5949 gfx::Rect
child_rect(10, 10, 50, 50);
5950 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5952 root
->SetHasRenderSurface(true);
5953 root
->SetPosition(root_rect
.origin());
5954 root
->SetBounds(root_rect
.size());
5955 root
->draw_properties().visible_layer_rect
= root_rect
;
5956 root
->SetDrawsContent(false);
5957 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5959 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5960 child
->SetOpacity(0.5f
);
5961 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5962 child
->draw_properties().visible_layer_rect
= child_rect
;
5963 child
->SetDrawsContent(false);
5964 child
->SetHasRenderSurface(true);
5966 grand_child
->SetPosition(grand_child_rect
.origin());
5967 grand_child
->SetBounds(grand_child_rect
.size());
5968 grand_child
->draw_properties().visible_layer_rect
= grand_child_rect
;
5969 grand_child
->SetDrawsContent(true);
5971 child
->AddChild(grand_child
.Pass());
5972 root
->AddChild(child
.Pass());
5974 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5975 return my_host_impl
.Pass();
5978 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5979 TestSharedBitmapManager shared_bitmap_manager
;
5980 TestTaskGraphRunner task_graph_runner
;
5981 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5982 SetupLayersForOpacity(true, this, &proxy_
, &shared_bitmap_manager
,
5983 &task_graph_runner
, &stats_instrumentation_
);
5985 LayerTreeHostImpl::FrameData frame
;
5986 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5988 // Verify all quads have been computed
5989 ASSERT_EQ(2U, frame
.render_passes
.size());
5990 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5991 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5992 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5993 frame
.render_passes
[0]->quad_list
.front()->material
);
5994 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5995 frame
.render_passes
[1]->quad_list
.front()->material
);
5997 my_host_impl
->DrawLayers(&frame
);
5998 my_host_impl
->DidDrawAllLayers(frame
);
6002 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
6003 TestSharedBitmapManager shared_bitmap_manager
;
6004 TestTaskGraphRunner task_graph_runner
;
6005 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
6006 SetupLayersForOpacity(false, this, &proxy_
, &shared_bitmap_manager
,
6007 &task_graph_runner
, &stats_instrumentation_
);
6009 LayerTreeHostImpl::FrameData frame
;
6010 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
6012 // Verify all quads have been computed
6013 ASSERT_EQ(2U, frame
.render_passes
.size());
6014 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
6015 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
6016 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
6017 frame
.render_passes
[0]->quad_list
.front()->material
);
6018 EXPECT_EQ(DrawQuad::RENDER_PASS
,
6019 frame
.render_passes
[1]->quad_list
.front()->material
);
6021 my_host_impl
->DrawLayers(&frame
);
6022 my_host_impl
->DidDrawAllLayers(frame
);
6026 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
6027 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6028 TestWebGraphicsContext3D::Create();
6029 TestWebGraphicsContext3D
* context3d
= context
.get();
6030 scoped_ptr
<OutputSurface
> output_surface(
6031 FakeOutputSurface::Create3d(context
.Pass()));
6032 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6034 scoped_ptr
<LayerImpl
> root_layer
=
6035 LayerImpl::Create(host_impl_
->active_tree(), 1);
6036 root_layer
->SetBounds(gfx::Size(10, 10));
6037 root_layer
->SetHasRenderSurface(true);
6039 scoped_refptr
<VideoFrame
> softwareFrame
=
6040 media::VideoFrame::CreateColorFrame(
6041 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
6042 FakeVideoFrameProvider provider
;
6043 provider
.set_frame(softwareFrame
);
6044 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6045 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
6046 video_layer
->SetBounds(gfx::Size(10, 10));
6047 video_layer
->SetDrawsContent(true);
6048 root_layer
->AddChild(video_layer
.Pass());
6050 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
6051 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
6052 io_surface_layer
->SetBounds(gfx::Size(10, 10));
6053 io_surface_layer
->SetDrawsContent(true);
6054 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
6055 root_layer
->AddChild(io_surface_layer
.Pass());
6057 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
6059 EXPECT_EQ(0u, context3d
->NumTextures());
6061 LayerTreeHostImpl::FrameData frame
;
6062 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6063 host_impl_
->DrawLayers(&frame
);
6064 host_impl_
->DidDrawAllLayers(frame
);
6065 host_impl_
->SwapBuffers(frame
);
6067 EXPECT_GT(context3d
->NumTextures(), 0u);
6069 // Kill the layer tree.
6070 host_impl_
->active_tree()->SetRootLayer(
6071 LayerImpl::Create(host_impl_
->active_tree(), 100));
6072 // There should be no textures left in use after.
6073 EXPECT_EQ(0u, context3d
->NumTextures());
6076 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
6078 MOCK_METHOD1(useProgram
, void(GLuint program
));
6079 MOCK_METHOD4(drawElements
, void(GLenum mode
,
6085 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
6086 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
6087 new MockDrawQuadsToFillScreenContext
);
6088 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
6091 LayerTreeSettings settings
= DefaultSettings();
6092 settings
.renderer_settings
.partial_swap_enabled
= false;
6093 CreateHostImpl(settings
,
6094 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
6095 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6096 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
6098 // Verify one quad is drawn when transparent background set is not set.
6099 host_impl_
->active_tree()->set_has_transparent_background(false);
6100 EXPECT_CALL(*mock_context
, useProgram(_
))
6102 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
6104 LayerTreeHostImpl::FrameData frame
;
6105 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6106 host_impl_
->DrawLayers(&frame
);
6107 host_impl_
->DidDrawAllLayers(frame
);
6108 Mock::VerifyAndClearExpectations(&mock_context
);
6110 // Verify no quads are drawn when transparent background is set.
6111 host_impl_
->active_tree()->set_has_transparent_background(true);
6112 host_impl_
->SetFullRootLayerDamage();
6113 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6114 host_impl_
->DrawLayers(&frame
);
6115 host_impl_
->DidDrawAllLayers(frame
);
6116 Mock::VerifyAndClearExpectations(&mock_context
);
6119 class LayerTreeHostImplTestWithDelegatingRenderer
6120 : public LayerTreeHostImplTest
{
6122 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
6123 return FakeOutputSurface::CreateDelegating3d();
6126 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
6127 bool expect_to_draw
= !expected_damage
.IsEmpty();
6129 LayerTreeHostImpl::FrameData frame
;
6130 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6132 if (!expect_to_draw
) {
6133 // With no damage, we don't draw, and no quads are created.
6134 ASSERT_EQ(0u, frame
.render_passes
.size());
6136 ASSERT_EQ(1u, frame
.render_passes
.size());
6138 // Verify the damage rect for the root render pass.
6139 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
6140 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
6142 // Verify the root and child layers' quads are generated and not being
6144 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
6146 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
6147 gfx::RectF
expected_child_visible_rect(child
->bounds());
6148 EXPECT_EQ(expected_child_visible_rect
,
6149 root_render_pass
->quad_list
.front()->visible_rect
);
6151 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
6152 gfx::RectF
expected_root_visible_rect(root
->bounds());
6153 EXPECT_EQ(expected_root_visible_rect
,
6154 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
6157 host_impl_
->DrawLayers(&frame
);
6158 host_impl_
->DidDrawAllLayers(frame
);
6159 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
6163 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
6164 scoped_ptr
<SolidColorLayerImpl
> root
=
6165 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6166 root
->SetPosition(gfx::PointF());
6167 root
->SetBounds(gfx::Size(10, 10));
6168 root
->SetDrawsContent(true);
6169 root
->SetHasRenderSurface(true);
6171 // Child layer is in the bottom right corner.
6172 scoped_ptr
<SolidColorLayerImpl
> child
=
6173 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
6174 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
6175 child
->SetBounds(gfx::Size(1, 1));
6176 child
->SetDrawsContent(true);
6177 root
->AddChild(child
.Pass());
6179 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6181 // Draw a frame. In the first frame, the entire viewport should be damaged.
6182 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6183 DrawFrameAndTestDamage(full_frame_damage
);
6185 // The second frame has damage that doesn't touch the child layer. Its quads
6186 // should still be generated.
6187 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
6188 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
6189 DrawFrameAndTestDamage(small_damage
);
6191 // The third frame should have no damage, so no quads should be generated.
6192 gfx::Rect no_damage
;
6193 DrawFrameAndTestDamage(no_damage
);
6196 // TODO(reveman): Remove this test and the ability to prevent on demand raster
6197 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
6198 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
6199 LayerTreeSettings settings
;
6200 CreateHostImpl(settings
, CreateOutputSurface());
6201 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
6204 class FakeMaskLayerImpl
: public LayerImpl
{
6206 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
6208 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
6211 void GetContentsResourceId(ResourceId
* resource_id
,
6212 gfx::Size
* resource_size
) const override
{
6217 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
6218 : LayerImpl(tree_impl
, id
) {}
6221 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
6223 using GLRenderer::ShouldAntialiasQuad
;
6226 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
6227 // Due to precision issues (especially on Android), sometimes far
6228 // away quads can end up thinking they need AA.
6229 float device_scale_factor
= 4.f
/ 3.f
;
6230 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
6231 gfx::Size
root_size(2000, 1000);
6232 gfx::Size device_viewport_size
=
6233 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
6234 host_impl_
->SetViewportSize(device_viewport_size
);
6236 host_impl_
->CreatePendingTree();
6237 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
6240 scoped_ptr
<LayerImpl
> scoped_root
=
6241 LayerImpl::Create(host_impl_
->pending_tree(), 1);
6242 LayerImpl
* root
= scoped_root
.get();
6243 root
->SetHasRenderSurface(true);
6245 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
6247 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
6248 LayerImpl::Create(host_impl_
->pending_tree(), 2);
6249 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
6250 root
->AddChild(scoped_scrolling_layer
.Pass());
6252 gfx::Size
content_layer_bounds(100000, 100);
6253 gfx::Size
pile_tile_size(3000, 3000);
6254 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
6255 pile_tile_size
, content_layer_bounds
));
6257 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
6258 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
6260 LayerImpl
* content_layer
= scoped_content_layer
.get();
6261 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
6262 content_layer
->SetBounds(content_layer_bounds
);
6263 content_layer
->SetDrawsContent(true);
6265 root
->SetBounds(root_size
);
6267 gfx::ScrollOffset
scroll_offset(100000, 0);
6268 scrolling_layer
->SetScrollClipLayer(root
->id());
6269 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
6271 host_impl_
->ActivateSyncTree();
6273 bool update_lcd_text
= false;
6274 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
6275 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
6277 LayerTreeHostImpl::FrameData frame
;
6278 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6280 ASSERT_EQ(1u, frame
.render_passes
.size());
6281 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
6282 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
6284 bool clipped
= false, force_aa
= false;
6285 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
6286 quad
->shared_quad_state
->quad_to_target_transform
,
6287 gfx::QuadF(quad
->shared_quad_state
->visible_quad_layer_rect
), &clipped
);
6288 EXPECT_FALSE(clipped
);
6290 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6291 device_layer_quad
, clipped
, force_aa
);
6292 EXPECT_FALSE(antialiased
);
6294 host_impl_
->DrawLayers(&frame
);
6295 host_impl_
->DidDrawAllLayers(frame
);
6299 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
6301 CompositorFrameMetadataTest()
6302 : swap_buffers_complete_(0) {}
6304 void DidSwapBuffersCompleteOnImplThread() override
{
6305 swap_buffers_complete_
++;
6308 int swap_buffers_complete_
;
6311 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
6312 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
6314 LayerTreeHostImpl::FrameData frame
;
6315 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6316 host_impl_
->DrawLayers(&frame
);
6317 host_impl_
->DidDrawAllLayers(frame
);
6319 CompositorFrameAck ack
;
6320 host_impl_
->ReclaimResources(&ack
);
6321 host_impl_
->DidSwapBuffersComplete();
6322 EXPECT_EQ(swap_buffers_complete_
, 1);
6325 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
6327 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6329 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
6331 return SoftwareOutputDevice::BeginPaint(damage_rect
);
6333 void EndPaint() override
{
6334 SoftwareOutputDevice::EndPaint();
6338 int frames_began_
, frames_ended_
;
6341 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
6342 // No main thread evictions in resourceless software mode.
6343 set_reduce_memory_result(false);
6344 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
6345 EXPECT_TRUE(CreateHostImpl(
6347 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
6348 host_impl_
->SetViewportSize(gfx::Size(50, 50));
6350 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6352 const gfx::Transform external_transform
;
6353 const gfx::Rect external_viewport
;
6354 const gfx::Rect external_clip
;
6355 const bool resourceless_software_draw
= true;
6356 host_impl_
->SetExternalDrawConstraints(external_transform
,
6361 resourceless_software_draw
);
6363 EXPECT_EQ(0, software_device
->frames_began_
);
6364 EXPECT_EQ(0, software_device
->frames_ended_
);
6368 EXPECT_EQ(1, software_device
->frames_began_
);
6369 EXPECT_EQ(1, software_device
->frames_ended_
);
6371 // Call another API method that is likely to hit nullptr in this mode.
6372 scoped_refptr
<base::trace_event::TracedValue
> state
=
6373 make_scoped_refptr(new base::trace_event::TracedValue());
6374 host_impl_
->ActivationStateAsValueInto(state
.get());
6377 TEST_F(LayerTreeHostImplTest
,
6378 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
6379 set_reduce_memory_result(false);
6380 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6381 FakeOutputSurface::CreateSoftware(
6382 make_scoped_ptr(new CountingSoftwareDevice
))));
6384 const gfx::Transform external_transform
;
6385 const gfx::Rect external_viewport
;
6386 const gfx::Rect external_clip
;
6387 const bool resourceless_software_draw
= true;
6388 host_impl_
->SetExternalDrawConstraints(external_transform
,
6393 resourceless_software_draw
);
6395 // SolidColorLayerImpl will be drawn.
6396 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
6397 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6399 // VideoLayerImpl will not be drawn.
6400 FakeVideoFrameProvider provider
;
6401 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6402 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
6403 video_layer
->SetBounds(gfx::Size(10, 10));
6404 video_layer
->SetDrawsContent(true);
6405 root_layer
->AddChild(video_layer
.Pass());
6406 SetupRootLayerImpl(root_layer
.Pass());
6408 LayerTreeHostImpl::FrameData frame
;
6409 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6410 host_impl_
->DrawLayers(&frame
);
6411 host_impl_
->DidDrawAllLayers(frame
);
6413 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
6414 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
6417 // Checks that we have a non-0 default allocation if we pass a context that
6418 // doesn't support memory management extensions.
6419 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
6420 LayerTreeSettings settings
;
6421 host_impl_
= LayerTreeHostImpl::Create(
6422 settings
, this, &proxy_
, &stats_instrumentation_
, &shared_bitmap_manager_
,
6423 &gpu_memory_buffer_manager_
, &task_graph_runner_
, 0);
6425 scoped_ptr
<OutputSurface
> output_surface(
6426 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6427 host_impl_
->InitializeRenderer(output_surface
.Pass());
6428 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
6431 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6432 ASSERT_TRUE(host_impl_
->active_tree());
6434 // RequiresHighResToDraw is set when new output surface is used.
6435 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6437 host_impl_
->ResetRequiresHighResToDraw();
6439 host_impl_
->SetVisible(false);
6440 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6441 host_impl_
->SetVisible(true);
6442 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6443 host_impl_
->SetVisible(false);
6444 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6446 host_impl_
->ResetRequiresHighResToDraw();
6448 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6449 host_impl_
->SetVisible(true);
6450 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6453 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6454 ASSERT_TRUE(host_impl_
->active_tree());
6455 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6457 // RequiresHighResToDraw is set when new output surface is used.
6458 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6460 host_impl_
->ResetRequiresHighResToDraw();
6462 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6463 host_impl_
->SetHasGpuRasterizationTrigger(false);
6464 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6465 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6466 host_impl_
->SetHasGpuRasterizationTrigger(true);
6467 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6468 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6469 host_impl_
->SetHasGpuRasterizationTrigger(false);
6470 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6471 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6473 host_impl_
->ResetRequiresHighResToDraw();
6475 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6476 host_impl_
->SetHasGpuRasterizationTrigger(true);
6477 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6478 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6481 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6483 void SetUp() override
{
6485 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_
,
6486 &shared_bitmap_manager_
, &task_graph_runner_
);
6487 host_impl_
.reset(fake_host_impl_
);
6488 host_impl_
->InitializeRenderer(CreateOutputSurface());
6489 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6492 FakeLayerTreeHostImpl
* fake_host_impl_
;
6495 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6496 fake_host_impl_
->DidModifyTilePriorities();
6497 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6498 fake_host_impl_
->SetVisible(false);
6499 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6502 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6503 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6504 TestWebGraphicsContext3D::Create();
6505 TestWebGraphicsContext3D
* context3d
= context
.get();
6506 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6507 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6509 EXPECT_EQ(0u, context3d
->NumTextures());
6511 UIResourceId ui_resource_id
= 1;
6512 bool is_opaque
= false;
6513 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6514 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6515 EXPECT_EQ(1u, context3d
->NumTextures());
6516 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6519 // Multiple requests with the same id is allowed. The previous texture is
6521 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6522 EXPECT_EQ(1u, context3d
->NumTextures());
6523 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6525 EXPECT_NE(id1
, id2
);
6527 // Deleting invalid UIResourceId is allowed and does not change state.
6528 host_impl_
->DeleteUIResource(-1);
6529 EXPECT_EQ(1u, context3d
->NumTextures());
6531 // Should return zero for invalid UIResourceId. Number of textures should
6533 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6534 EXPECT_EQ(1u, context3d
->NumTextures());
6536 host_impl_
->DeleteUIResource(ui_resource_id
);
6537 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6538 EXPECT_EQ(0u, context3d
->NumTextures());
6540 // Should not change state for multiple deletion on one UIResourceId
6541 host_impl_
->DeleteUIResource(ui_resource_id
);
6542 EXPECT_EQ(0u, context3d
->NumTextures());
6545 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6546 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6547 TestWebGraphicsContext3D::Create();
6548 TestWebGraphicsContext3D
* context3d
= context
.get();
6549 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6551 EXPECT_EQ(0u, context3d
->NumTextures());
6553 gfx::Size
size(4, 4);
6554 // SkImageInfo has no support for ETC1. The |info| below contains the right
6555 // total pixel size for the bitmap but not the right height and width. The
6556 // correct width/height are passed directly to UIResourceBitmap.
6558 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6559 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6560 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6561 pixel_ref
->setImmutable();
6562 UIResourceBitmap
bitmap(pixel_ref
, size
);
6563 UIResourceId ui_resource_id
= 1;
6564 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6565 EXPECT_EQ(1u, context3d
->NumTextures());
6566 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6570 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6573 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6574 scoped_refptr
<TestContextProvider
> context_provider
=
6575 TestContextProvider::Create();
6577 CreateHostImpl(DefaultSettings(),
6578 FakeOutputSurface::Create3d(context_provider
));
6580 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6582 ScopedPtrVector
<CopyOutputRequest
> requests
;
6583 requests
.push_back(CopyOutputRequest::CreateRequest(
6584 base::Bind(&ShutdownReleasesContext_Callback
)));
6586 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6588 LayerTreeHostImpl::FrameData frame
;
6589 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6590 host_impl_
->DrawLayers(&frame
);
6591 host_impl_
->DidDrawAllLayers(frame
);
6593 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6594 // texture in a texture mailbox.
6595 EXPECT_FALSE(context_provider
->HasOneRef());
6596 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6598 host_impl_
= nullptr;
6600 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6601 // released, and the texture deleted.
6602 EXPECT_TRUE(context_provider
->HasOneRef());
6603 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6606 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6607 // When flinging via touch, only the child should scroll (we should not
6609 gfx::Size
surface_size(10, 10);
6610 gfx::Size
content_size(20, 20);
6611 scoped_ptr
<LayerImpl
> root_clip
=
6612 LayerImpl::Create(host_impl_
->active_tree(), 3);
6613 root_clip
->SetHasRenderSurface(true);
6615 scoped_ptr
<LayerImpl
> root
=
6616 CreateScrollableLayer(1, content_size
, root_clip
.get());
6617 root
->SetIsContainerForFixedPositionLayers(true);
6618 scoped_ptr
<LayerImpl
> child
=
6619 CreateScrollableLayer(2, content_size
, root_clip
.get());
6621 root
->AddChild(child
.Pass());
6622 int root_id
= root
->id();
6623 root_clip
->AddChild(root
.Pass());
6625 host_impl_
->SetViewportSize(surface_size
);
6626 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6627 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6629 host_impl_
->active_tree()->DidBecomeActive();
6632 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6633 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6635 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6637 gfx::Vector2d
scroll_delta(0, 100);
6638 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6639 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6641 host_impl_
->ScrollEnd();
6643 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6644 host_impl_
->ProcessScrollDeltas();
6646 // Only the child should have scrolled.
6647 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6648 ExpectNone(*scroll_info
.get(), root_id
);
6652 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6653 // Scroll a child layer beyond its maximum scroll range and make sure the
6654 // the scroll doesn't bubble up to the parent layer.
6655 gfx::Size
surface_size(10, 10);
6656 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6657 root
->SetHasRenderSurface(true);
6658 scoped_ptr
<LayerImpl
> root_scrolling
=
6659 CreateScrollableLayer(2, surface_size
, root
.get());
6661 scoped_ptr
<LayerImpl
> grand_child
=
6662 CreateScrollableLayer(4, surface_size
, root
.get());
6663 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6665 scoped_ptr
<LayerImpl
> child
=
6666 CreateScrollableLayer(3, surface_size
, root
.get());
6667 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6668 child
->AddChild(grand_child
.Pass());
6670 root_scrolling
->AddChild(child
.Pass());
6671 root
->AddChild(root_scrolling
.Pass());
6672 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6673 host_impl_
->active_tree()->DidBecomeActive();
6674 host_impl_
->SetViewportSize(surface_size
);
6677 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6679 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6680 LayerImpl
* grand_child
= child
->children()[0];
6682 gfx::Vector2d
scroll_delta(0, -2);
6683 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6684 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6685 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6687 // The grand child should have scrolled up to its limit.
6688 scroll_info
= host_impl_
->ProcessScrollDeltas();
6689 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6691 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6692 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6694 // The child should have received the bubbled delta, but the locked
6695 // scrolling layer should remain set as the grand child.
6696 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6697 scroll_info
= host_impl_
->ProcessScrollDeltas();
6698 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6700 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6701 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(), scroll_delta
));
6702 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6704 // The first |ScrollBy| after the fling should re-lock the scrolling
6705 // layer to the first layer that scrolled, which is the child.
6706 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6707 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6708 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6710 // The child should have scrolled up to its limit.
6711 scroll_info
= host_impl_
->ProcessScrollDeltas();
6712 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6714 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6715 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(),
6716 scroll_delta
+ scroll_delta
));
6718 // As the locked layer is at it's limit, no further scrolling can occur.
6719 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6720 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6721 host_impl_
->ScrollEnd();
6725 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6726 // When flinging via wheel, the root should eventually scroll (we should
6728 gfx::Size
surface_size(10, 10);
6729 gfx::Size
content_size(20, 20);
6730 scoped_ptr
<LayerImpl
> root_clip
=
6731 LayerImpl::Create(host_impl_
->active_tree(), 3);
6732 root_clip
->SetHasRenderSurface(true);
6733 scoped_ptr
<LayerImpl
> root_scroll
=
6734 CreateScrollableLayer(1, content_size
, root_clip
.get());
6735 int root_scroll_id
= root_scroll
->id();
6736 scoped_ptr
<LayerImpl
> child
=
6737 CreateScrollableLayer(2, content_size
, root_clip
.get());
6739 root_scroll
->AddChild(child
.Pass());
6740 root_clip
->AddChild(root_scroll
.Pass());
6742 host_impl_
->SetViewportSize(surface_size
);
6743 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6744 host_impl_
->active_tree()->DidBecomeActive();
6747 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6748 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6750 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6752 gfx::Vector2d
scroll_delta(0, 100);
6753 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6754 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6756 host_impl_
->ScrollEnd();
6758 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6759 host_impl_
->ProcessScrollDeltas();
6761 // The root should have scrolled.
6762 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6763 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll_id
,
6764 gfx::Vector2d(0, 10)));
6768 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6769 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6770 // we should return SCROLL_UNKNOWN.
6771 gfx::Size
content_size(100, 100);
6772 SetupScrollAndContentsLayers(content_size
);
6774 int scroll_layer_id
= 2;
6775 LayerImpl
* scroll_layer
=
6776 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6777 scroll_layer
->SetDrawsContent(true);
6779 int page_scale_layer_id
= 5;
6780 LayerImpl
* page_scale_layer
=
6781 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6783 int occluder_layer_id
= 6;
6784 scoped_ptr
<LayerImpl
> occluder_layer
=
6785 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6786 occluder_layer
->SetDrawsContent(true);
6787 occluder_layer
->SetBounds(content_size
);
6788 occluder_layer
->SetPosition(gfx::PointF());
6790 // The parent of the occluder is *above* the scroller.
6791 page_scale_layer
->AddChild(occluder_layer
.Pass());
6795 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6796 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6799 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6800 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6801 // is not the first scroller we encounter when walking up from the layer, we
6802 // should also return SCROLL_UNKNOWN.
6803 gfx::Size
content_size(100, 100);
6804 SetupScrollAndContentsLayers(content_size
);
6806 int scroll_layer_id
= 2;
6807 LayerImpl
* scroll_layer
=
6808 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6809 scroll_layer
->SetDrawsContent(true);
6811 int occluder_layer_id
= 6;
6812 scoped_ptr
<LayerImpl
> occluder_layer
=
6813 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6814 occluder_layer
->SetDrawsContent(true);
6815 occluder_layer
->SetBounds(content_size
);
6816 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6818 int child_scroll_clip_layer_id
= 7;
6819 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6820 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6822 int child_scroll_layer_id
= 8;
6823 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6824 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6826 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6828 child_scroll
->AddChild(occluder_layer
.Pass());
6829 scroll_layer
->AddChild(child_scroll
.Pass());
6833 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6834 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6837 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6838 gfx::Size
content_size(100, 100);
6839 SetupScrollAndContentsLayers(content_size
);
6841 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6843 int scroll_layer_id
= 2;
6844 LayerImpl
* scroll_layer
=
6845 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6847 int child_scroll_layer_id
= 7;
6848 scoped_ptr
<LayerImpl
> child_scroll
=
6849 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6850 child_scroll
->SetDrawsContent(false);
6852 scroll_layer
->AddChild(child_scroll
.Pass());
6856 // We should not have scrolled |child_scroll| even though we technically "hit"
6857 // it. The reason for this is that if the scrolling the scroll would not move
6858 // any layer that is a drawn RSLL member, then we can ignore the hit.
6860 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6861 // started scrolling the inner viewport.
6862 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6863 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6865 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6868 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6869 gfx::Size
content_size(100, 100);
6870 SetupScrollAndContentsLayers(content_size
);
6872 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6873 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6875 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6876 CreateScrollableLayer(7, content_size
, root
);
6877 invisible_scroll_layer
->SetDrawsContent(false);
6879 scoped_ptr
<LayerImpl
> child_layer
=
6880 LayerImpl::Create(host_impl_
->active_tree(), 8);
6881 child_layer
->SetDrawsContent(false);
6883 scoped_ptr
<LayerImpl
> grand_child_layer
=
6884 LayerImpl::Create(host_impl_
->active_tree(), 9);
6885 grand_child_layer
->SetDrawsContent(true);
6886 grand_child_layer
->SetBounds(content_size
);
6887 // Move the grand child so it's not hit by our test point.
6888 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6890 child_layer
->AddChild(grand_child_layer
.Pass());
6891 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6892 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6896 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6897 // a descendant which is a drawn RSLL member.
6898 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6899 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6901 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6904 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6905 // This test case is very similar to the one above with one key difference:
6906 // the invisible scroller has a scroll child that is indeed draw contents.
6907 // If we attempt to initiate a gesture scroll off of the visible scroll child
6908 // we should still start the scroll child.
6909 gfx::Size
content_size(100, 100);
6910 SetupScrollAndContentsLayers(content_size
);
6912 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6914 int scroll_layer_id
= 2;
6915 LayerImpl
* scroll_layer
=
6916 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6918 int scroll_child_id
= 6;
6919 scoped_ptr
<LayerImpl
> scroll_child
=
6920 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6921 scroll_child
->SetDrawsContent(true);
6922 scroll_child
->SetBounds(content_size
);
6923 // Move the scroll child so it's not hit by our test point.
6924 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6926 int invisible_scroll_layer_id
= 7;
6927 scoped_ptr
<LayerImpl
> invisible_scroll
=
6928 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6929 invisible_scroll
->SetDrawsContent(false);
6931 int container_id
= 8;
6932 scoped_ptr
<LayerImpl
> container
=
6933 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6935 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6936 scroll_children
->insert(scroll_child
.get());
6937 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6939 scroll_child
->SetScrollParent(invisible_scroll
.get());
6941 container
->AddChild(invisible_scroll
.Pass());
6942 container
->AddChild(scroll_child
.Pass());
6944 scroll_layer
->AddChild(container
.Pass());
6948 // We should have scrolled |child_scroll| even though it is invisible.
6949 // The reason for this is that if the scrolling the scroll would move a layer
6950 // that is a drawn RSLL member, then we should accept this hit.
6951 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6952 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6954 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6957 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6958 // to CompositorFrameMetadata after SwapBuffers();
6959 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6960 scoped_ptr
<SolidColorLayerImpl
> root
=
6961 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6962 root
->SetPosition(gfx::PointF());
6963 root
->SetBounds(gfx::Size(10, 10));
6964 root
->SetDrawsContent(true);
6965 root
->SetHasRenderSurface(true);
6967 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6969 FakeOutputSurface
* fake_output_surface
=
6970 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6972 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6973 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6974 EXPECT_TRUE(metadata_latency_before
.empty());
6976 ui::LatencyInfo latency_info
;
6977 latency_info
.AddLatencyNumber(
6978 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6979 scoped_ptr
<SwapPromise
> swap_promise(
6980 new LatencyInfoSwapPromise(latency_info
));
6981 host_impl_
->active_tree()->QueuePinnedSwapPromise(swap_promise
.Pass());
6982 host_impl_
->SetNeedsRedraw();
6984 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6985 LayerTreeHostImpl::FrameData frame
;
6986 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6987 host_impl_
->DrawLayers(&frame
);
6988 host_impl_
->DidDrawAllLayers(frame
);
6989 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6991 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6992 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6993 EXPECT_EQ(1u, metadata_latency_after
.size());
6994 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6995 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6998 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6999 int root_layer_id
= 1;
7000 scoped_ptr
<SolidColorLayerImpl
> root
=
7001 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
7002 root
->SetPosition(gfx::PointF());
7003 root
->SetBounds(gfx::Size(10, 10));
7004 root
->SetDrawsContent(true);
7005 root
->SetHasRenderSurface(true);
7007 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
7009 // Ensure the default frame selection bounds are empty.
7010 FakeOutputSurface
* fake_output_surface
=
7011 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
7012 const ViewportSelection
& selection_before
=
7013 fake_output_surface
->last_sent_frame().metadata
.selection
;
7014 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
7015 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
7017 // Plumb the layer-local selection bounds.
7018 gfx::PointF
selection_top(5, 0);
7019 gfx::PointF
selection_bottom(5, 5);
7020 LayerSelection selection
;
7021 selection
.start
.type
= SELECTION_BOUND_CENTER
;
7022 selection
.start
.layer_id
= root_layer_id
;
7023 selection
.start
.edge_bottom
= selection_bottom
;
7024 selection
.start
.edge_top
= selection_top
;
7025 selection
.end
= selection
.start
;
7026 host_impl_
->active_tree()->RegisterSelection(selection
);
7028 // Trigger a draw-swap sequence.
7029 host_impl_
->SetNeedsRedraw();
7031 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
7032 LayerTreeHostImpl::FrameData frame
;
7033 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
7034 host_impl_
->DrawLayers(&frame
);
7035 host_impl_
->DidDrawAllLayers(frame
);
7036 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
7038 // Ensure the selection bounds have propagated to the frame metadata.
7039 const ViewportSelection
& selection_after
=
7040 fake_output_surface
->last_sent_frame().metadata
.selection
;
7041 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
7042 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
7043 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
7044 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
7045 EXPECT_TRUE(selection_after
.start
.visible
);
7046 EXPECT_TRUE(selection_after
.start
.visible
);
7049 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
7051 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
7052 LayerTreeHostImpl
* layer_tree_host_impl
,
7053 int* set_needs_commit_count
,
7054 int* set_needs_redraw_count
,
7055 int* forward_to_main_count
)
7056 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
7057 set_needs_commit_count_(set_needs_commit_count
),
7058 set_needs_redraw_count_(set_needs_redraw_count
),
7059 forward_to_main_count_(forward_to_main_count
) {}
7061 ~SimpleSwapPromiseMonitor() override
{}
7063 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
7065 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
7067 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
7068 (*forward_to_main_count_
)++;
7072 int* set_needs_commit_count_
;
7073 int* set_needs_redraw_count_
;
7074 int* forward_to_main_count_
;
7077 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
7078 int set_needs_commit_count
= 0;
7079 int set_needs_redraw_count
= 0;
7080 int forward_to_main_count
= 0;
7083 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7084 new SimpleSwapPromiseMonitor(NULL
,
7086 &set_needs_commit_count
,
7087 &set_needs_redraw_count
,
7088 &forward_to_main_count
));
7089 host_impl_
->SetNeedsRedraw();
7090 EXPECT_EQ(0, set_needs_commit_count
);
7091 EXPECT_EQ(1, set_needs_redraw_count
);
7092 EXPECT_EQ(0, forward_to_main_count
);
7095 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7097 host_impl_
->SetNeedsRedraw();
7098 EXPECT_EQ(0, set_needs_commit_count
);
7099 EXPECT_EQ(1, set_needs_redraw_count
);
7100 EXPECT_EQ(0, forward_to_main_count
);
7103 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7104 new SimpleSwapPromiseMonitor(NULL
,
7106 &set_needs_commit_count
,
7107 &set_needs_redraw_count
,
7108 &forward_to_main_count
));
7109 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
7110 EXPECT_EQ(0, set_needs_commit_count
);
7111 EXPECT_EQ(2, set_needs_redraw_count
);
7112 EXPECT_EQ(0, forward_to_main_count
);
7116 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7117 new SimpleSwapPromiseMonitor(NULL
,
7119 &set_needs_commit_count
,
7120 &set_needs_redraw_count
,
7121 &forward_to_main_count
));
7122 // Empty damage rect won't signal the monitor.
7123 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
7124 EXPECT_EQ(0, set_needs_commit_count
);
7125 EXPECT_EQ(2, set_needs_redraw_count
);
7126 EXPECT_EQ(0, forward_to_main_count
);
7130 set_needs_commit_count
= 0;
7131 set_needs_redraw_count
= 0;
7132 forward_to_main_count
= 0;
7133 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7134 new SimpleSwapPromiseMonitor(NULL
,
7136 &set_needs_commit_count
,
7137 &set_needs_redraw_count
,
7138 &forward_to_main_count
));
7139 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7141 // Scrolling normally should not trigger any forwarding.
7142 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7143 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7145 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7146 host_impl_
->ScrollEnd();
7148 EXPECT_EQ(0, set_needs_commit_count
);
7149 EXPECT_EQ(1, set_needs_redraw_count
);
7150 EXPECT_EQ(0, forward_to_main_count
);
7152 // Scrolling with a scroll handler should defer the swap to the main
7154 scroll_layer
->SetHaveScrollEventHandlers(true);
7155 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7156 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7158 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7159 host_impl_
->ScrollEnd();
7161 EXPECT_EQ(0, set_needs_commit_count
);
7162 EXPECT_EQ(2, set_needs_redraw_count
);
7163 EXPECT_EQ(1, forward_to_main_count
);
7167 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
7169 void SetUp() override
{
7170 LayerTreeSettings settings
= DefaultSettings();
7171 CreateHostImpl(settings
, CreateOutputSurface());
7172 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
7173 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
7174 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
7178 static const int top_controls_height_
;
7181 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
7183 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
7184 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7185 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7186 BeginFrameArgs begin_frame_args
=
7187 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7188 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7189 host_impl_
->Animate();
7190 EXPECT_FALSE(did_request_redraw_
);
7191 host_impl_
->DidFinishImplFrame();
7194 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
7195 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7196 EXPECT_FALSE(did_request_redraw_
);
7197 host_impl_
->CreatePendingTree();
7198 host_impl_
->sync_tree()->set_top_controls_height(100);
7199 host_impl_
->ActivateSyncTree();
7200 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
7203 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7204 TopControlsStayFullyVisibleOnHeightChange
) {
7205 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7206 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7208 host_impl_
->CreatePendingTree();
7209 host_impl_
->sync_tree()->set_top_controls_height(0);
7210 host_impl_
->ActivateSyncTree();
7211 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7213 host_impl_
->CreatePendingTree();
7214 host_impl_
->sync_tree()->set_top_controls_height(50);
7215 host_impl_
->ActivateSyncTree();
7216 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7219 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
7220 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7221 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7222 host_impl_
->DidChangeTopControlsPosition();
7223 EXPECT_TRUE(did_request_animate_
);
7224 EXPECT_TRUE(did_request_redraw_
);
7227 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
7228 InputHandlerScrollResult result
;
7229 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7230 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7231 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7232 BOTH
, SHOWN
, false);
7235 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7236 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7237 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7238 EXPECT_EQ(gfx::Vector2dF().ToString(),
7239 scroll_layer
->CurrentScrollOffset().ToString());
7241 // Scroll just the top controls and verify that the scroll succeeds.
7242 const float residue
= 10;
7243 float offset
= top_controls_height_
- residue
;
7244 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7245 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7246 EXPECT_TRUE(result
.did_scroll
);
7247 EXPECT_FLOAT_EQ(-offset
,
7248 host_impl_
->top_controls_manager()->ControlsTopOffset());
7249 EXPECT_EQ(gfx::Vector2dF().ToString(),
7250 scroll_layer
->CurrentScrollOffset().ToString());
7252 // Scroll across the boundary
7253 const float content_scroll
= 20;
7254 offset
= residue
+ content_scroll
;
7255 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7256 EXPECT_TRUE(result
.did_scroll
);
7257 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7258 EXPECT_EQ(-top_controls_height_
,
7259 host_impl_
->top_controls_manager()->ControlsTopOffset());
7260 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
7261 scroll_layer
->CurrentScrollOffset().ToString());
7263 // Now scroll back to the top of the content
7264 offset
= -content_scroll
;
7265 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7266 EXPECT_TRUE(result
.did_scroll
);
7267 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7268 EXPECT_EQ(-top_controls_height_
,
7269 host_impl_
->top_controls_manager()->ControlsTopOffset());
7270 EXPECT_EQ(gfx::Vector2dF().ToString(),
7271 scroll_layer
->CurrentScrollOffset().ToString());
7273 // And scroll the top controls completely into view
7274 offset
= -top_controls_height_
;
7275 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7276 EXPECT_TRUE(result
.did_scroll
);
7277 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7278 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7279 EXPECT_EQ(gfx::Vector2dF().ToString(),
7280 scroll_layer
->CurrentScrollOffset().ToString());
7282 // And attempt to scroll past the end
7283 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7284 EXPECT_FALSE(result
.did_scroll
);
7285 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, -50));
7286 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7287 EXPECT_EQ(gfx::Vector2dF().ToString(),
7288 scroll_layer
->CurrentScrollOffset().ToString());
7290 host_impl_
->ScrollEnd();
7293 TEST_F(LayerTreeHostImplWithTopControlsTest
, WheelUnhandledByTopControls
) {
7294 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7295 host_impl_
->SetViewportSize(gfx::Size(50, 100));
7296 host_impl_
->active_tree()->set_top_controls_shrink_blink_size(true);
7297 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7301 LayerImpl
* viewport_layer
= host_impl_
->InnerViewportScrollLayer();
7303 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7304 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7305 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7306 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer
->CurrentScrollOffset());
7308 // Wheel scrolls should not affect the top controls, and should pass
7309 // directly through to the viewport.
7310 const float delta
= top_controls_height_
;
7312 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7313 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7314 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
),
7315 viewport_layer
->CurrentScrollOffset());
7318 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7319 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7320 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
* 2),
7321 viewport_layer
->CurrentScrollOffset());
7324 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
7325 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7326 host_impl_
->SetViewportSize(gfx::Size(100, 200));
7327 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7328 BOTH
, SHOWN
, false);
7331 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7332 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7333 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7334 EXPECT_EQ(gfx::Vector2dF().ToString(),
7335 scroll_layer
->CurrentScrollOffset().ToString());
7337 // Scroll the top controls partially.
7338 const float residue
= 35;
7339 float offset
= top_controls_height_
- residue
;
7341 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7342 EXPECT_FLOAT_EQ(-offset
,
7343 host_impl_
->top_controls_manager()->ControlsTopOffset());
7344 EXPECT_EQ(gfx::Vector2dF().ToString(),
7345 scroll_layer
->CurrentScrollOffset().ToString());
7347 did_request_redraw_
= false;
7348 did_request_animate_
= false;
7349 did_request_commit_
= false;
7351 // End the scroll while the controls are still offset from their limit.
7352 host_impl_
->ScrollEnd();
7353 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7354 EXPECT_TRUE(did_request_animate_
);
7355 EXPECT_TRUE(did_request_redraw_
);
7356 EXPECT_FALSE(did_request_commit_
);
7358 // The top controls should properly animate until finished, despite the scroll
7359 // offset being at the origin.
7360 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7361 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7362 while (did_request_animate_
) {
7363 did_request_redraw_
= false;
7364 did_request_animate_
= false;
7365 did_request_commit_
= false;
7368 host_impl_
->top_controls_manager()->ControlsTopOffset();
7370 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7371 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7372 host_impl_
->Animate();
7373 EXPECT_EQ(gfx::Vector2dF().ToString(),
7374 scroll_layer
->CurrentScrollOffset().ToString());
7377 host_impl_
->top_controls_manager()->ControlsTopOffset();
7379 // No commit is needed as the controls are animating the content offset,
7380 // not the scroll offset.
7381 EXPECT_FALSE(did_request_commit_
);
7383 if (new_offset
!= old_offset
)
7384 EXPECT_TRUE(did_request_redraw_
);
7386 if (new_offset
!= 0) {
7387 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
7388 EXPECT_TRUE(did_request_animate_
);
7390 host_impl_
->DidFinishImplFrame();
7392 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7395 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
7396 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7397 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7398 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7399 BOTH
, SHOWN
, false);
7400 float initial_scroll_offset
= 50;
7401 scroll_layer
->PushScrollOffsetFromMainThread(
7402 gfx::ScrollOffset(0, initial_scroll_offset
));
7405 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7406 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7407 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7408 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7409 scroll_layer
->CurrentScrollOffset().ToString());
7411 // Scroll the top controls partially.
7412 const float residue
= 15;
7413 float offset
= top_controls_height_
- residue
;
7415 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7416 EXPECT_FLOAT_EQ(-offset
,
7417 host_impl_
->top_controls_manager()->ControlsTopOffset());
7418 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7419 scroll_layer
->CurrentScrollOffset().ToString());
7421 did_request_redraw_
= false;
7422 did_request_animate_
= false;
7423 did_request_commit_
= false;
7425 // End the scroll while the controls are still offset from the limit.
7426 host_impl_
->ScrollEnd();
7427 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7428 EXPECT_TRUE(did_request_animate_
);
7429 EXPECT_TRUE(did_request_redraw_
);
7430 EXPECT_FALSE(did_request_commit_
);
7432 // Animate the top controls to the limit.
7433 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7434 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7435 while (did_request_animate_
) {
7436 did_request_redraw_
= false;
7437 did_request_animate_
= false;
7438 did_request_commit_
= false;
7441 host_impl_
->top_controls_manager()->ControlsTopOffset();
7443 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7444 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7445 host_impl_
->Animate();
7448 host_impl_
->top_controls_manager()->ControlsTopOffset();
7450 if (new_offset
!= old_offset
) {
7451 EXPECT_TRUE(did_request_redraw_
);
7452 EXPECT_TRUE(did_request_commit_
);
7454 host_impl_
->DidFinishImplFrame();
7456 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7457 EXPECT_EQ(-top_controls_height_
,
7458 host_impl_
->top_controls_manager()->ControlsTopOffset());
7461 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7462 TopControlsAnimationAfterMainThreadFlingStopped
) {
7463 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7464 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7465 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7467 float initial_scroll_offset
= 50;
7468 scroll_layer
->PushScrollOffsetFromMainThread(
7469 gfx::ScrollOffset(0, initial_scroll_offset
));
7472 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7473 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7474 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7475 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7476 scroll_layer
->CurrentScrollOffset().ToString());
7478 // Scroll the top controls partially.
7479 const float residue
= 15;
7480 float offset
= top_controls_height_
- residue
;
7482 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7483 EXPECT_FLOAT_EQ(-offset
,
7484 host_impl_
->top_controls_manager()->ControlsTopOffset());
7485 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7486 scroll_layer
->CurrentScrollOffset().ToString());
7488 did_request_redraw_
= false;
7489 did_request_animate_
= false;
7490 did_request_commit_
= false;
7492 // End the fling while the controls are still offset from the limit.
7493 host_impl_
->MainThreadHasStoppedFlinging();
7494 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7495 EXPECT_TRUE(did_request_animate_
);
7496 EXPECT_TRUE(did_request_redraw_
);
7497 EXPECT_FALSE(did_request_commit_
);
7499 // Animate the top controls to the limit.
7500 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7501 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7502 while (did_request_animate_
) {
7503 did_request_redraw_
= false;
7504 did_request_animate_
= false;
7505 did_request_commit_
= false;
7507 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7509 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7510 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7511 host_impl_
->Animate();
7513 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7515 if (new_offset
!= old_offset
) {
7516 EXPECT_TRUE(did_request_redraw_
);
7517 EXPECT_TRUE(did_request_commit_
);
7519 host_impl_
->DidFinishImplFrame();
7521 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7522 EXPECT_EQ(-top_controls_height_
,
7523 host_impl_
->top_controls_manager()->ControlsTopOffset());
7526 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7527 TopControlsScrollDeltaInOverScroll
) {
7528 // Verifies that the overscroll delta should not have accumulated in
7529 // the top controls if we do a hide and show without releasing finger.
7531 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7532 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7533 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7537 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7538 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7539 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7543 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7544 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7545 EXPECT_EQ(gfx::Vector2dF().ToString(),
7546 scroll_layer
->CurrentScrollOffset().ToString());
7549 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7550 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7551 scroll_layer
->CurrentScrollOffset().ToString());
7554 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7556 // Should have fully scrolled
7557 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7558 scroll_layer
->CurrentScrollOffset().ToString());
7560 float overscrollamount
= 10;
7562 // Overscroll the content
7564 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7566 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7567 scroll_layer
->CurrentScrollOffset().ToString());
7568 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7569 host_impl_
->accumulated_root_overscroll().ToString());
7571 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7573 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7574 scroll_layer
->CurrentScrollOffset().ToString());
7575 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7578 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7579 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7580 scroll_layer
->CurrentScrollOffset().ToString());
7582 // Top controls should be fully visible
7583 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7585 host_impl_
->ScrollEnd();
7588 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7590 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7591 const gfx::Size
& outer_viewport
,
7592 const gfx::Size
& inner_viewport
) {
7593 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7594 const int kOuterViewportClipLayerId
= 6;
7595 const int kOuterViewportScrollLayerId
= 7;
7596 const int kInnerViewportScrollLayerId
= 2;
7597 const int kInnerViewportClipLayerId
= 4;
7598 const int kPageScaleLayerId
= 5;
7600 scoped_ptr
<LayerImpl
> inner_scroll
=
7601 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7602 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7603 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7605 scoped_ptr
<LayerImpl
> inner_clip
=
7606 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7607 inner_clip
->SetBounds(inner_viewport
);
7609 scoped_ptr
<LayerImpl
> page_scale
=
7610 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7612 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7613 inner_scroll
->SetBounds(outer_viewport
);
7614 inner_scroll
->SetPosition(gfx::PointF());
7616 scoped_ptr
<LayerImpl
> outer_clip
=
7617 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7618 outer_clip
->SetBounds(outer_viewport
);
7619 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7621 scoped_ptr
<LayerImpl
> outer_scroll
=
7622 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7623 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7624 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7625 outer_scroll
->SetBounds(content_size
);
7626 outer_scroll
->SetPosition(gfx::PointF());
7628 scoped_ptr
<LayerImpl
> contents
=
7629 LayerImpl::Create(layer_tree_impl
, 8);
7630 contents
->SetDrawsContent(true);
7631 contents
->SetBounds(content_size
);
7632 contents
->SetPosition(gfx::PointF());
7634 outer_scroll
->AddChild(contents
.Pass());
7635 outer_clip
->AddChild(outer_scroll
.Pass());
7636 inner_scroll
->AddChild(outer_clip
.Pass());
7637 page_scale
->AddChild(inner_scroll
.Pass());
7638 inner_clip
->AddChild(page_scale
.Pass());
7640 inner_clip
->SetHasRenderSurface(true);
7641 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7642 layer_tree_impl
->SetViewportLayersFromIds(
7643 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7644 kOuterViewportScrollLayerId
);
7646 host_impl_
->active_tree()->DidBecomeActive();
7650 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7651 gfx::Size content_size
= gfx::Size(100, 160);
7652 gfx::Size outer_viewport
= gfx::Size(50, 80);
7653 gfx::Size inner_viewport
= gfx::Size(25, 40);
7655 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7657 TestScrollOffsetDelegate scroll_delegate
;
7658 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7660 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7661 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7664 gfx::ScrollOffset inner_expected
;
7665 gfx::ScrollOffset outer_expected
;
7666 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7667 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7669 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7671 scroll_delegate
.set_getter_return_value(current_offset
);
7672 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
7673 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7674 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7676 // Outer viewport scrolls first. Then the rest is applied to the inner
7678 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7679 inner_scroll
->CurrentScrollOffset());
7680 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7681 outer_scroll
->CurrentScrollOffset());
7685 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7686 gfx::Size content_size
= gfx::Size(100, 160);
7687 gfx::Size outer_viewport
= gfx::Size(50, 80);
7688 gfx::Size inner_viewport
= gfx::Size(25, 40);
7690 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7692 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7693 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7696 gfx::Vector2dF inner_expected
;
7697 gfx::Vector2dF outer_expected
;
7698 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7699 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7701 // Make sure the fling goes to the outer viewport first
7702 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7703 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7704 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7705 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7706 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7708 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7709 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7710 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7711 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), outer_scroll
);
7713 host_impl_
->ScrollEnd();
7714 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7716 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7717 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7719 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7720 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7721 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7722 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7723 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7724 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7726 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7727 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7728 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7730 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7731 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7732 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7734 host_impl_
->ScrollEnd();
7735 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7737 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7738 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7742 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7743 DiagonalScrollBubblesPerfectlyToInner
) {
7744 gfx::Size content_size
= gfx::Size(100, 160);
7745 gfx::Size outer_viewport
= gfx::Size(50, 80);
7746 gfx::Size inner_viewport
= gfx::Size(25, 40);
7748 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7750 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7751 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7754 gfx::Vector2dF inner_expected
;
7755 gfx::Vector2dF outer_expected
;
7756 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7757 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7759 // Make sure the scroll goes to the outer viewport first.
7760 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7761 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7762 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7763 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7764 InputHandler::GESTURE
));
7766 // Scroll near the edge of the outer viewport.
7767 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7768 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7769 outer_expected
+= scroll_delta
;
7770 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7771 InputHandler::GESTURE
));
7773 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7774 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7776 // Now diagonal scroll across the outer viewport boundary in a single event.
7777 // The entirety of the scroll should be consumed, as bubbling between inner
7778 // and outer viewport layers is perfect.
7779 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7780 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7781 InputHandler::GESTURE
));
7782 outer_expected
+= scroll_delta
;
7783 inner_expected
+= scroll_delta
;
7784 host_impl_
->ScrollEnd();
7785 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7786 gfx::Point(), InputHandler::GESTURE
));
7788 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7789 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7793 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7794 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7795 gfx::Size content_size
= gfx::Size(100, 160);
7796 gfx::Size outer_viewport
= gfx::Size(50, 80);
7797 gfx::Size inner_viewport
= gfx::Size(25, 40);
7799 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7801 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7802 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7804 scoped_ptr
<LayerImpl
> child
=
7805 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7806 LayerImpl
* child_scroll
= child
.get();
7807 outer_scroll
->children()[0]->AddChild(child
.Pass());
7811 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7813 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7814 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7815 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7816 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7817 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7818 InputHandler::GESTURE
));
7820 // The child should have scrolled up to its limit.
7821 scroll_info
= host_impl_
->ProcessScrollDeltas();
7822 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7824 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7825 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7827 // The first |ScrollBy| after the fling should re-lock the scrolling
7828 // layer to the first layer that scrolled, the inner viewport scroll layer.
7829 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7830 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7831 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7832 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7833 InputHandler::GESTURE
));
7835 // The inner viewport should have scrolled up to its limit.
7836 scroll_info
= host_impl_
->ProcessScrollDeltas();
7837 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7839 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7841 ScrollInfoContains(*scroll_info
, inner_scroll
->id(), scroll_delta
));
7843 // As the locked layer is at its limit, no further scrolling can occur.
7844 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7845 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7846 host_impl_
->ScrollEnd();
7847 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7848 gfx::Point(), InputHandler::GESTURE
));
7852 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7853 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest
) {
7854 gfx::Size content_size
= gfx::Size(100, 160);
7855 gfx::Size outer_viewport
= gfx::Size(50, 80);
7856 gfx::Size inner_viewport
= gfx::Size(25, 40);
7858 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7860 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7861 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7863 scoped_ptr
<LayerImpl
> child
=
7864 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7865 LayerImpl
* child_scroll
= child
.get();
7866 outer_scroll
->children()[0]->AddChild(child
.Pass());
7870 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7871 host_impl_
->RootScrollBegin(InputHandler::GESTURE
));
7872 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7873 host_impl_
->ScrollEnd();
7874 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7875 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7876 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7877 host_impl_
->ScrollEnd();
7880 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7881 NoOverscrollWhenInnerViewportCantScroll
) {
7882 InputHandlerScrollResult scroll_result
;
7883 gfx::Size content_size
= gfx::Size(100, 160);
7884 gfx::Size outer_viewport
= gfx::Size(50, 80);
7885 gfx::Size inner_viewport
= gfx::Size(25, 40);
7886 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7889 // Make inner viewport unscrollable.
7890 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7891 inner_scroll
->set_user_scrollable_horizontal(false);
7892 inner_scroll
->set_user_scrollable_vertical(false);
7894 // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
7895 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7896 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7897 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7898 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
7899 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7901 // When inner viewport is unscrollable, a fling gives zero overscroll.
7902 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
7903 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
7906 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7908 void SetUp() override
{
7909 LayerTreeSettings settings
= DefaultSettings();
7910 settings
.max_memory_for_prepaint_percentage
= 50;
7911 CreateHostImpl(settings
, CreateOutputSurface());
7915 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7916 // Set up a memory policy and percentages which could cause
7917 // 32-bit integer overflows.
7918 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7920 // Verify implicit limits are calculated correctly with no overflows
7921 host_impl_
->SetMemoryPolicy(mem_policy
);
7922 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7923 300u * 1024u * 1024u);
7924 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7925 150u * 1024u * 1024u);
7928 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7929 const gfx::Size
layer_size(100, 100);
7930 gfx::Transform external_transform
;
7931 const gfx::Rect
external_viewport(layer_size
);
7932 const gfx::Rect
external_clip(layer_size
);
7933 const bool resourceless_software_draw
= false;
7934 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7936 host_impl_
->SetExternalDrawConstraints(external_transform
,
7941 resourceless_software_draw
);
7943 EXPECT_TRANSFORMATION_MATRIX_EQ(
7944 external_transform
, layer
->draw_properties().target_space_transform
);
7946 external_transform
.Translate(20, 20);
7947 host_impl_
->SetExternalDrawConstraints(external_transform
,
7952 resourceless_software_draw
);
7954 EXPECT_TRANSFORMATION_MATRIX_EQ(
7955 external_transform
, layer
->draw_properties().target_space_transform
);
7958 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7959 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7962 base::TimeTicks start_time
=
7963 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7965 BeginFrameArgs begin_frame_args
=
7966 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7968 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7969 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7971 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7973 begin_frame_args
.frame_time
= start_time
;
7974 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7975 host_impl_
->Animate();
7976 host_impl_
->UpdateAnimationState(true);
7978 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7979 host_impl_
->DidFinishImplFrame();
7981 begin_frame_args
.frame_time
=
7982 start_time
+ base::TimeDelta::FromMilliseconds(50);
7983 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7984 host_impl_
->Animate();
7985 host_impl_
->UpdateAnimationState(true);
7987 float y
= scrolling_layer
->CurrentScrollOffset().y();
7988 EXPECT_TRUE(y
> 1 && y
< 49);
7991 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7992 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7993 host_impl_
->DidFinishImplFrame();
7995 begin_frame_args
.frame_time
=
7996 start_time
+ base::TimeDelta::FromMilliseconds(200);
7997 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7998 host_impl_
->Animate();
7999 host_impl_
->UpdateAnimationState(true);
8001 y
= scrolling_layer
->CurrentScrollOffset().y();
8002 EXPECT_TRUE(y
> 50 && y
< 100);
8003 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
8004 host_impl_
->DidFinishImplFrame();
8006 begin_frame_args
.frame_time
=
8007 start_time
+ base::TimeDelta::FromMilliseconds(250);
8008 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8009 host_impl_
->Animate();
8010 host_impl_
->UpdateAnimationState(true);
8012 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8013 scrolling_layer
->CurrentScrollOffset());
8014 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
8015 host_impl_
->DidFinishImplFrame();
8018 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
8019 TEST_F(LayerTreeHostImplTimelinesTest
, ScrollAnimated
) {
8020 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8023 base::TimeTicks start_time
=
8024 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8026 BeginFrameArgs begin_frame_args
=
8027 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8029 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8030 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8032 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
8034 begin_frame_args
.frame_time
= start_time
;
8035 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8036 host_impl_
->Animate();
8037 host_impl_
->UpdateAnimationState(true);
8039 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
8040 host_impl_
->DidFinishImplFrame();
8042 begin_frame_args
.frame_time
=
8043 start_time
+ base::TimeDelta::FromMilliseconds(50);
8044 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8045 host_impl_
->Animate();
8046 host_impl_
->UpdateAnimationState(true);
8048 float y
= scrolling_layer
->CurrentScrollOffset().y();
8049 EXPECT_TRUE(y
> 1 && y
< 49);
8052 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8053 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8054 host_impl_
->DidFinishImplFrame();
8056 begin_frame_args
.frame_time
=
8057 start_time
+ base::TimeDelta::FromMilliseconds(200);
8058 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8059 host_impl_
->Animate();
8060 host_impl_
->UpdateAnimationState(true);
8062 y
= scrolling_layer
->CurrentScrollOffset().y();
8063 EXPECT_TRUE(y
> 50 && y
< 100);
8064 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
8065 host_impl_
->DidFinishImplFrame();
8067 begin_frame_args
.frame_time
=
8068 start_time
+ base::TimeDelta::FromMilliseconds(250);
8069 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8070 host_impl_
->Animate();
8071 host_impl_
->UpdateAnimationState(true);
8073 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8074 scrolling_layer
->CurrentScrollOffset());
8075 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
8076 host_impl_
->DidFinishImplFrame();
8079 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
8080 host_impl_
->CreatePendingTree();
8082 Region empty_invalidation
;
8083 scoped_refptr
<RasterSource
> pile_with_tiles(
8084 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
8085 gfx::Size(10, 10)));
8087 scoped_ptr
<FakePictureLayerImpl
> layer
=
8088 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
8089 layer
->SetBounds(gfx::Size(10, 10));
8090 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
8091 layer
->SetDrawsContent(true);
8092 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
8093 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
8094 layer
->tilings()->tiling_at(0)->set_resolution(
8095 TileResolution::HIGH_RESOLUTION
);
8096 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
8097 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
8098 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
8099 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
8101 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
8102 host_impl_
->pending_tree()->root_layer());
8104 root_layer
->set_has_valid_tile_priorities(true);
8105 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
8106 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8107 RasterTilePriorityQueue::Type::ALL
);
8108 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
8110 root_layer
->set_has_valid_tile_priorities(false);
8111 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
8112 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8113 RasterTilePriorityQueue::Type::ALL
);
8114 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
8117 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
8118 host_impl_
->CreatePendingTree();
8119 host_impl_
->ActivateSyncTree();
8120 host_impl_
->CreatePendingTree();
8122 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
8124 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
8125 FakePictureLayerImpl::Create(pending_tree
, 10);
8126 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
8127 pending_tree
->SetRootLayer(pending_layer
.Pass());
8128 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
8130 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
8131 pending_tree
->DidBecomeActive();
8132 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8134 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
8135 FakePictureLayerImpl::Create(pending_tree
, 11);
8136 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
8137 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
8138 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
8140 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8141 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
8142 pending_tree
->DidBecomeActive();
8143 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8144 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8146 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
8147 FakePictureLayerImpl::Create(pending_tree
, 12);
8148 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
8149 FakePictureLayerImpl::Create(pending_tree
, 13);
8150 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
8151 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
8152 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
8153 ASSERT_EQ(raw_replica_mask_layer
,
8154 raw_pending_layer
->replica_layer()->mask_layer());
8156 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8157 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8158 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
8159 pending_tree
->DidBecomeActive();
8160 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
8161 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
8162 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
8165 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
8166 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
8167 host_impl_
->SetViewportSize(gfx::Size(50, 50));
8170 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
8172 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
8173 float page_scale_factor
= 1.f
;
8175 // The scroll deltas should have the page scale factor applied.
8177 host_impl_
->active_tree()->PushPageScaleFromMainThread(
8178 page_scale_factor
, min_page_scale
, max_page_scale
);
8179 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
8180 scroll_layer
->SetScrollDelta(gfx::Vector2d());
8182 float page_scale_delta
= 2.f
;
8183 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
8184 host_impl_
->PinchGestureBegin();
8185 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
8186 host_impl_
->PinchGestureEnd();
8187 host_impl_
->ScrollEnd();
8189 gfx::Vector2dF
scroll_delta(0, 5);
8190 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8191 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
8192 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
8194 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
8195 host_impl_
->ScrollEnd();
8196 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8197 scroll_layer
->CurrentScrollOffset());
8201 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
8203 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8204 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
8207 int num_lost_surfaces_
;
8210 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
8211 // Really we just need at least one client notification each time
8212 // we go from having a valid output surface to not having a valid output
8214 EXPECT_EQ(0, num_lost_surfaces_
);
8215 host_impl_
->DidLoseOutputSurface();
8216 EXPECT_EQ(1, num_lost_surfaces_
);
8217 host_impl_
->DidLoseOutputSurface();
8218 EXPECT_LE(1, num_lost_surfaces_
);
8221 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
8222 LayerTreeHostImpl::FrameData frame
;
8223 frame
.render_passes
.push_back(RenderPass::Create());
8224 RenderPass
* pass3
= frame
.render_passes
.back();
8225 frame
.render_passes
.push_back(RenderPass::Create());
8226 RenderPass
* pass2
= frame
.render_passes
.back();
8227 frame
.render_passes
.push_back(RenderPass::Create());
8228 RenderPass
* pass1
= frame
.render_passes
.back();
8230 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8231 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8232 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8234 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8235 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8236 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8238 // Add a quad to each pass so they aren't empty.
8239 SolidColorDrawQuad
* color_quad
;
8240 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8241 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8242 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8243 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8244 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8245 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8247 // pass3 is referenced by pass2.
8248 RenderPassDrawQuad
* rpdq
=
8249 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8250 rpdq
->material
= DrawQuad::RENDER_PASS
;
8251 rpdq
->render_pass_id
= pass3
->id
;
8253 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
8254 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8255 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8256 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8257 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8258 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8259 EXPECT_EQ(1u, frame
.render_passes
.size());
8260 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8263 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
8264 LayerTreeHostImpl::FrameData frame
;
8265 frame
.render_passes
.push_back(RenderPass::Create());
8266 RenderPass
* pass3
= frame
.render_passes
.back();
8267 frame
.render_passes
.push_back(RenderPass::Create());
8268 RenderPass
* pass2
= frame
.render_passes
.back();
8269 frame
.render_passes
.push_back(RenderPass::Create());
8270 RenderPass
* pass1
= frame
.render_passes
.back();
8272 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8273 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8274 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8276 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8277 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8278 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8280 // pass1 is not empty, but pass2 and pass3 are.
8281 SolidColorDrawQuad
* color_quad
;
8282 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8283 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8285 // pass3 is referenced by pass2.
8286 RenderPassDrawQuad
* rpdq
=
8287 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8288 rpdq
->material
= DrawQuad::RENDER_PASS
;
8289 rpdq
->render_pass_id
= pass3
->id
;
8291 // pass2 is referenced by pass1.
8292 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8293 rpdq
->material
= DrawQuad::RENDER_PASS
;
8294 rpdq
->render_pass_id
= pass2
->id
;
8296 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8297 // should be removed.
8298 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8299 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8300 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8301 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8302 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8303 EXPECT_EQ(1u, frame
.render_passes
.size());
8304 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8305 // The RenderPassDrawQuad should be removed from pass1.
8306 EXPECT_EQ(1u, pass1
->quad_list
.size());
8307 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
8310 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
8311 LayerTreeHostImpl::FrameData frame
;
8312 frame
.render_passes
.push_back(RenderPass::Create());
8313 RenderPass
* pass3
= frame
.render_passes
.back();
8314 frame
.render_passes
.push_back(RenderPass::Create());
8315 RenderPass
* pass2
= frame
.render_passes
.back();
8316 frame
.render_passes
.push_back(RenderPass::Create());
8317 RenderPass
* pass1
= frame
.render_passes
.back();
8319 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8320 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8321 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8323 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8324 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8325 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8327 // pass3 is referenced by pass2.
8328 RenderPassDrawQuad
* rpdq
=
8329 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8330 rpdq
->material
= DrawQuad::RENDER_PASS
;
8331 rpdq
->render_pass_id
= pass3
->id
;
8333 // pass2 is referenced by pass1.
8334 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8335 rpdq
->material
= DrawQuad::RENDER_PASS
;
8336 rpdq
->render_pass_id
= pass2
->id
;
8338 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8339 // should be removed. Then pass1 is empty too, but it's the root so it should
8341 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8342 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8343 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8344 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8345 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8346 EXPECT_EQ(1u, frame
.render_passes
.size());
8347 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8348 // The RenderPassDrawQuad should be removed from pass1.
8349 EXPECT_EQ(0u, pass1
->quad_list
.size());
8352 class FakeVideoFrameController
: public VideoFrameController
{
8354 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
8355 begin_frame_args_
= args
;
8356 did_draw_frame_
= false;
8359 void DidDrawFrame() override
{ did_draw_frame_
= true; }
8361 const BeginFrameArgs
& begin_frame_args() const { return begin_frame_args_
; }
8363 bool did_draw_frame() const { return did_draw_frame_
; }
8366 BeginFrameArgs begin_frame_args_
;
8367 bool did_draw_frame_
= false;
8370 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
8371 BeginFrameArgs begin_frame_args
=
8372 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8373 FakeVideoFrameController controller
;
8375 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8376 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8377 host_impl_
->AddVideoFrameController(&controller
);
8378 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8379 host_impl_
->DidFinishImplFrame();
8381 EXPECT_FALSE(controller
.did_draw_frame());
8382 LayerTreeHostImpl::FrameData frame
;
8383 host_impl_
->DidDrawAllLayers(frame
);
8384 EXPECT_TRUE(controller
.did_draw_frame());
8386 controller
.OnBeginFrame(begin_frame_args
);
8387 EXPECT_FALSE(controller
.did_draw_frame());
8388 host_impl_
->RemoveVideoFrameController(&controller
);
8389 host_impl_
->DidDrawAllLayers(frame
);
8390 EXPECT_FALSE(controller
.did_draw_frame());
8393 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
8394 BeginFrameArgs begin_frame_args
=
8395 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8396 FakeVideoFrameController controller
;
8398 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8399 host_impl_
->DidFinishImplFrame();
8401 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8402 host_impl_
->AddVideoFrameController(&controller
);
8403 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8405 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8406 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8407 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8408 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8410 EXPECT_FALSE(controller
.did_draw_frame());
8411 LayerTreeHostImpl::FrameData frame
;
8412 host_impl_
->DidDrawAllLayers(frame
);
8413 EXPECT_TRUE(controller
.did_draw_frame());
8415 controller
.OnBeginFrame(begin_frame_args
);
8416 EXPECT_FALSE(controller
.did_draw_frame());
8417 host_impl_
->RemoveVideoFrameController(&controller
);
8418 host_impl_
->DidDrawAllLayers(frame
);
8419 EXPECT_FALSE(controller
.did_draw_frame());
8422 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
8423 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8425 host_impl_
->SetHasGpuRasterizationTrigger(true);
8426 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8427 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
8428 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8430 host_impl_
->SetHasGpuRasterizationTrigger(false);
8431 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8432 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
8433 host_impl_
->gpu_rasterization_status());
8434 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8436 host_impl_
->SetHasGpuRasterizationTrigger(true);
8437 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8438 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
8439 host_impl_
->gpu_rasterization_status());
8440 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8441 EXPECT_FALSE(host_impl_
->use_msaa());
8443 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
8444 TestWebGraphicsContext3D::Create();
8445 context_with_msaa
->SetMaxSamples(8);
8447 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
8448 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
8449 EXPECT_TRUE(CreateHostImpl(
8450 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
8451 host_impl_
->SetHasGpuRasterizationTrigger(true);
8452 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8453 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
8454 host_impl_
->gpu_rasterization_status());
8455 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8456 EXPECT_TRUE(host_impl_
->use_msaa());
8458 LayerTreeSettings settings
= DefaultSettings();
8459 settings
.gpu_rasterization_enabled
= false;
8460 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8461 host_impl_
->SetHasGpuRasterizationTrigger(true);
8462 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8463 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
8464 host_impl_
->gpu_rasterization_status());
8465 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8467 settings
.gpu_rasterization_forced
= true;
8468 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8470 host_impl_
->SetHasGpuRasterizationTrigger(false);
8471 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8472 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
8473 host_impl_
->gpu_rasterization_status());
8474 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8477 // A mock output surface which lets us detect calls to ForceReclaimResources.
8478 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
8480 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
8481 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8482 TestContextProvider::Create(), TestContextProvider::Create(), false));
8485 MOCK_METHOD0(ForceReclaimResources
, void());
8488 MockReclaimResourcesOutputSurface(
8489 scoped_refptr
<ContextProvider
> context_provider
,
8490 scoped_refptr
<ContextProvider
> worker_context_provider
,
8491 bool delegated_rendering
)
8492 : FakeOutputSurface(context_provider
,
8493 worker_context_provider
,
8494 delegated_rendering
) {}
8497 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8498 // being reclaimed to block drawing between BeginCommit / Swap. This test
8499 // ensures that BeginCommit triggers ForceReclaimResources. See
8500 // crbug.com/489515.
8501 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
8502 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
8503 MockReclaimResourcesOutputSurface::Create3d());
8504 // Hold an unowned pointer to the output surface to use for mock expectations.
8505 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
8507 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
8508 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
8509 host_impl_
->BeginCommit();