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_
->active_tree()->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_
->active_tree()->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 CreateHostImpl(settings
,
1239 CreateOutputSurface());
1240 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.25f
, 4.f
);
1242 const gfx::Size
content_size(1000, 1000);
1243 const gfx::Size
viewport_size(500, 500);
1244 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1246 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1247 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1250 gfx::Vector2dF(500, 500),
1251 outer_scroll_layer
->MaxScrollOffset());
1253 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1254 host_impl_
->PinchGestureBegin();
1255 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1256 host_impl_
->PinchGestureEnd();
1257 host_impl_
->ScrollEnd();
1259 // Sanity check - we're zoomed in, starting from the origin.
1261 gfx::Vector2dF(0, 0),
1262 outer_scroll_layer
->CurrentScrollOffset());
1264 gfx::Vector2dF(0, 0),
1265 inner_scroll_layer
->CurrentScrollOffset());
1267 // Scroll down - only the inner viewport should scroll.
1268 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1269 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1270 host_impl_
->ScrollEnd();
1273 gfx::Vector2dF(50, 50),
1274 inner_scroll_layer
->CurrentScrollOffset());
1276 gfx::Vector2dF(0, 0),
1277 outer_scroll_layer
->CurrentScrollOffset());
1279 // Scroll down - outer viewport should start scrolling after the inner is at
1281 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1282 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f
, 1000.f
));
1283 host_impl_
->ScrollEnd();
1286 gfx::Vector2dF(250, 250),
1287 inner_scroll_layer
->CurrentScrollOffset());
1289 gfx::Vector2dF(300, 300),
1290 outer_scroll_layer
->CurrentScrollOffset());
1293 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1294 // as expected. That is, scrolling during a pinch should bubble from the inner
1295 // to the outer viewport.
1296 TEST_F(LayerTreeHostImplTest
, ScrollDuringPinchGesture
) {
1297 LayerTreeSettings settings
= DefaultSettings();
1298 CreateHostImpl(settings
,
1299 CreateOutputSurface());
1300 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1302 const gfx::Size
content_size(1000, 1000);
1303 const gfx::Size
viewport_size(500, 500);
1304 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1306 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1307 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1310 gfx::Vector2dF(500, 500),
1311 outer_scroll_layer
->MaxScrollOffset());
1313 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1314 host_impl_
->PinchGestureBegin();
1316 host_impl_
->PinchGestureUpdate(2, gfx::Point(250, 250));
1318 gfx::Vector2dF(0, 0),
1319 outer_scroll_layer
->CurrentScrollOffset());
1321 gfx::Vector2dF(125, 125),
1322 inner_scroll_layer
->CurrentScrollOffset());
1324 // Needed so that the pinch is accounted for in draw properties.
1327 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f
, 10.f
));
1329 gfx::Vector2dF(0, 0),
1330 outer_scroll_layer
->CurrentScrollOffset());
1332 gfx::Vector2dF(130, 130),
1333 inner_scroll_layer
->CurrentScrollOffset());
1337 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f
, 400.f
));
1339 gfx::Vector2dF(80, 80),
1340 outer_scroll_layer
->CurrentScrollOffset());
1342 gfx::Vector2dF(250, 250),
1343 inner_scroll_layer
->CurrentScrollOffset());
1345 host_impl_
->PinchGestureEnd();
1346 host_impl_
->ScrollEnd();
1349 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1350 // a pinch zoom is anchored within a certain margin of the screen edge, we
1351 // should assume the user means to scroll into the edge of the screen.
1352 TEST_F(LayerTreeHostImplTest
, PinchZoomSnapsToScreenEdge
) {
1353 LayerTreeSettings settings
= DefaultSettings();
1354 CreateHostImpl(settings
,
1355 CreateOutputSurface());
1356 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1358 const gfx::Size
content_size(1000, 1000);
1359 const gfx::Size
viewport_size(500, 500);
1360 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1362 int offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
- 5;
1363 gfx::Point
anchor(viewport_size
.width() - offsetFromEdge
,
1364 viewport_size
.height() - offsetFromEdge
);
1366 // Pinch in within the margins. The scroll should stay exactly locked to the
1367 // bottom and right.
1368 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1369 host_impl_
->PinchGestureBegin();
1370 host_impl_
->PinchGestureUpdate(2, anchor
);
1371 host_impl_
->PinchGestureEnd();
1372 host_impl_
->ScrollEnd();
1375 gfx::Vector2dF(250, 250),
1376 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1379 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1380 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1381 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1383 // Pinch in within the margins. The scroll should stay exactly locked to the
1385 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1386 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1387 host_impl_
->PinchGestureBegin();
1388 host_impl_
->PinchGestureUpdate(2, anchor
);
1389 host_impl_
->PinchGestureEnd();
1390 host_impl_
->ScrollEnd();
1393 gfx::Vector2dF(0, 0),
1394 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1397 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1398 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1399 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1401 // Pinch in just outside the margin. There should be no snapping.
1402 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1403 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1404 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1405 host_impl_
->PinchGestureBegin();
1406 host_impl_
->PinchGestureUpdate(2, anchor
);
1407 host_impl_
->PinchGestureEnd();
1408 host_impl_
->ScrollEnd();
1411 gfx::Vector2dF(50, 50),
1412 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1415 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1416 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1417 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1419 // Pinch in just outside the margin. There should be no snapping.
1420 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1421 anchor
= gfx::Point(viewport_size
.width() - offsetFromEdge
,
1422 viewport_size
.height() - offsetFromEdge
);
1423 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1424 host_impl_
->PinchGestureBegin();
1425 host_impl_
->PinchGestureUpdate(2, anchor
);
1426 host_impl_
->PinchGestureEnd();
1427 host_impl_
->ScrollEnd();
1430 gfx::Vector2dF(200, 200),
1431 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1434 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1435 const gfx::Size
content_size(200, 200);
1436 const gfx::Size
viewport_size(100, 100);
1437 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1439 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1440 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1442 // Zoom into the page by a 2X factor
1443 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1444 float page_scale_factor
= 2.f
;
1445 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1446 page_scale_factor
, min_page_scale
, max_page_scale
);
1447 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
1449 // Scroll by a small amount, there should be no bubbling to the outer
1451 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1452 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1453 host_impl_
->ScrollEnd();
1456 gfx::Vector2dF(5, 10),
1457 inner_scroll_layer
->CurrentScrollOffset());
1460 outer_scroll_layer
->CurrentScrollOffset());
1462 // Scroll by the inner viewport's max scroll extent, the remainder
1463 // should bubble up to the outer viewport.
1464 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1465 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1466 host_impl_
->ScrollEnd();
1469 gfx::Vector2dF(50, 50),
1470 inner_scroll_layer
->CurrentScrollOffset());
1472 gfx::Vector2dF(5, 10),
1473 outer_scroll_layer
->CurrentScrollOffset());
1475 // Scroll by the outer viewport's max scroll extent, it should all go to the
1477 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1478 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(190.f
, 180.f
));
1479 host_impl_
->ScrollEnd();
1482 gfx::Vector2dF(100, 100),
1483 outer_scroll_layer
->CurrentScrollOffset());
1485 gfx::Vector2dF(50, 50),
1486 inner_scroll_layer
->CurrentScrollOffset());
1489 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1490 ui::LatencyInfo latency_info
;
1491 latency_info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0,
1493 scoped_ptr
<SwapPromise
> swap_promise(
1494 new LatencyInfoSwapPromise(latency_info
));
1496 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1497 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1498 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1499 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1500 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1501 host_impl_
->ScrollEnd();
1503 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1504 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1505 EXPECT_EQ(latency_info
.trace_id(), scroll_info
->swap_promises
[0]->TraceId());
1508 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1509 // up to the scroll_parent, rather than the stacking parent.
1510 TEST_F(LayerTreeHostImplTest
, ScrollBubblesToScrollParent
) {
1511 LayerImpl
* viewport_scroll
=
1512 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1513 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1515 // Set up two scrolling children of the root, one of which is a scroll parent
1516 // to the other. Scrolls bubbling from the child should bubble to the parent,
1517 // not the viewport.
1520 LayerImpl
*child_clip
;
1522 scoped_ptr
<LayerImpl
> scroll_parent_clip
=
1523 LayerImpl::Create(host_impl_
->active_tree(), 6);
1524 scoped_ptr
<LayerImpl
> scroll_parent
= CreateScrollableLayer(
1525 7, gfx::Size(10, 10), scroll_parent_clip
.get());
1526 parent
= scroll_parent
.get();
1527 scroll_parent_clip
->AddChild(scroll_parent
.Pass());
1529 viewport_scroll
->AddChild(scroll_parent_clip
.Pass());
1531 scoped_ptr
<LayerImpl
> scroll_child_clip
=
1532 LayerImpl::Create(host_impl_
->active_tree(), 8);
1533 scoped_ptr
<LayerImpl
> scroll_child
= CreateScrollableLayer(
1534 9, gfx::Size(10, 10), scroll_child_clip
.get());
1535 child
= scroll_child
.get();
1536 scroll_child
->SetPosition(gfx::Point(20, 20));
1537 scroll_child_clip
->AddChild(scroll_child
.Pass());
1539 child_clip
= scroll_child_clip
.get();
1540 viewport_scroll
->AddChild(scroll_child_clip
.Pass());
1542 child_clip
->SetScrollParent(parent
);
1547 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1548 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1549 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1550 host_impl_
->ScrollEnd();
1552 // The child should be fully scrolled by the first ScrollBy.
1553 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child
->CurrentScrollOffset());
1555 // The scroll_parent should receive the bubbled up second ScrollBy.
1556 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent
->CurrentScrollOffset());
1558 // The viewport shouldn't have been scrolled at all.
1560 gfx::Vector2dF(0, 0),
1561 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1563 gfx::Vector2dF(0, 0),
1564 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1568 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1569 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1570 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1571 host_impl_
->ScrollEnd();
1573 // The first ScrollBy should scroll the parent to its extent.
1574 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent
->CurrentScrollOffset());
1576 // The viewport should now be next in bubbling order.
1578 gfx::Vector2dF(2, 1),
1579 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1581 gfx::Vector2dF(0, 0),
1582 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1587 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1588 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1589 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1592 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1593 DCHECK(scroll_layer
);
1595 float min_page_scale
= 1.f
;
1596 float max_page_scale
= 4.f
;
1598 // Basic pinch zoom in gesture
1600 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1602 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1604 float page_scale_delta
= 2.f
;
1605 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1606 host_impl_
->PinchGestureBegin();
1607 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1608 host_impl_
->PinchGestureEnd();
1609 host_impl_
->ScrollEnd();
1610 EXPECT_FALSE(did_request_animate_
);
1611 EXPECT_TRUE(did_request_redraw_
);
1612 EXPECT_TRUE(did_request_commit_
);
1614 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1615 host_impl_
->ProcessScrollDeltas();
1616 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1621 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1623 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1624 float page_scale_delta
= 10.f
;
1626 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1627 host_impl_
->PinchGestureBegin();
1628 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1629 host_impl_
->PinchGestureEnd();
1630 host_impl_
->ScrollEnd();
1632 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1633 host_impl_
->ProcessScrollDeltas();
1634 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1637 // Zoom-out clamping
1639 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1641 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1642 scroll_layer
->PullDeltaForMainThread();
1643 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1645 float page_scale_delta
= 0.1f
;
1646 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1647 host_impl_
->PinchGestureBegin();
1648 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1649 host_impl_
->PinchGestureEnd();
1650 host_impl_
->ScrollEnd();
1652 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1653 host_impl_
->ProcessScrollDeltas();
1654 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1656 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1659 // Two-finger panning should not happen based on pinch events only
1661 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1663 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1664 scroll_layer
->PullDeltaForMainThread();
1665 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1667 float page_scale_delta
= 1.f
;
1668 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1669 host_impl_
->PinchGestureBegin();
1670 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1671 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1672 host_impl_
->PinchGestureEnd();
1673 host_impl_
->ScrollEnd();
1675 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1676 host_impl_
->ProcessScrollDeltas();
1677 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1678 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1681 // Two-finger panning should work with interleaved scroll events
1683 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1685 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1686 scroll_layer
->PullDeltaForMainThread();
1687 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1689 float page_scale_delta
= 1.f
;
1690 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1691 host_impl_
->PinchGestureBegin();
1692 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1693 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1694 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1695 host_impl_
->PinchGestureEnd();
1696 host_impl_
->ScrollEnd();
1698 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1699 host_impl_
->ProcessScrollDeltas();
1700 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1701 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1702 gfx::Vector2d(-10, -10)));
1705 // Two-finger panning should work when starting fully zoomed out.
1707 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1708 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1709 scroll_layer
->PullDeltaForMainThread();
1710 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1712 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1713 host_impl_
->PinchGestureBegin();
1714 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1715 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1717 // Needed so layer transform includes page scale.
1720 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1721 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1722 host_impl_
->PinchGestureEnd();
1723 host_impl_
->ScrollEnd();
1725 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1726 host_impl_
->ProcessScrollDeltas();
1727 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1728 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1729 gfx::Vector2d(10, 10)));
1733 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1734 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1735 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1738 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1739 DCHECK(scroll_layer
);
1741 float min_page_scale
= 0.5f
;
1742 float max_page_scale
= 4.f
;
1743 base::TimeTicks start_time
= base::TimeTicks() +
1744 base::TimeDelta::FromSeconds(1);
1745 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1746 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1747 base::TimeTicks end_time
= start_time
+ duration
;
1749 BeginFrameArgs begin_frame_args
=
1750 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1752 // Non-anchor zoom-in
1754 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1756 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1758 did_request_redraw_
= false;
1759 did_request_animate_
= false;
1760 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1761 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1766 host_impl_
->ActivateSyncTree();
1767 EXPECT_FALSE(did_request_redraw_
);
1768 EXPECT_TRUE(did_request_animate_
);
1770 did_request_redraw_
= false;
1771 did_request_animate_
= false;
1772 begin_frame_args
.frame_time
= start_time
;
1773 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1774 host_impl_
->Animate();
1775 EXPECT_TRUE(did_request_redraw_
);
1776 EXPECT_TRUE(did_request_animate_
);
1777 host_impl_
->DidFinishImplFrame();
1779 did_request_redraw_
= false;
1780 did_request_animate_
= false;
1781 begin_frame_args
.frame_time
= halfway_through_animation
;
1782 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1783 host_impl_
->Animate();
1784 EXPECT_TRUE(did_request_redraw_
);
1785 EXPECT_TRUE(did_request_animate_
);
1786 host_impl_
->DidFinishImplFrame();
1788 did_request_redraw_
= false;
1789 did_request_animate_
= false;
1790 did_request_commit_
= false;
1791 begin_frame_args
.frame_time
= end_time
;
1792 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1793 host_impl_
->Animate();
1794 EXPECT_TRUE(did_request_commit_
);
1795 EXPECT_FALSE(did_request_animate_
);
1796 host_impl_
->DidFinishImplFrame();
1798 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1799 host_impl_
->ProcessScrollDeltas();
1800 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1801 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1802 gfx::Vector2d(-50, -50)));
1805 start_time
+= base::TimeDelta::FromSeconds(10);
1806 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1807 end_time
+= base::TimeDelta::FromSeconds(10);
1811 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1813 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1815 did_request_redraw_
= false;
1816 did_request_animate_
= false;
1817 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1818 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1819 gfx::Vector2d(25, 25),
1823 host_impl_
->ActivateSyncTree();
1824 EXPECT_FALSE(did_request_redraw_
);
1825 EXPECT_TRUE(did_request_animate_
);
1827 did_request_redraw_
= false;
1828 did_request_animate_
= false;
1829 begin_frame_args
.frame_time
= start_time
;
1830 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1831 host_impl_
->Animate();
1832 EXPECT_TRUE(did_request_redraw_
);
1833 EXPECT_TRUE(did_request_animate_
);
1834 host_impl_
->DidFinishImplFrame();
1836 did_request_redraw_
= false;
1837 did_request_commit_
= false;
1838 did_request_animate_
= false;
1839 begin_frame_args
.frame_time
= end_time
;
1840 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1841 host_impl_
->Animate();
1842 EXPECT_TRUE(did_request_redraw_
);
1843 EXPECT_FALSE(did_request_animate_
);
1844 EXPECT_TRUE(did_request_commit_
);
1845 host_impl_
->DidFinishImplFrame();
1847 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1848 host_impl_
->ProcessScrollDeltas();
1849 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1850 // Pushed to (0,0) via clamping against contents layer size.
1851 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1852 gfx::Vector2d(-50, -50)));
1856 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1857 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1858 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1861 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1862 DCHECK(scroll_layer
);
1864 float min_page_scale
= 0.5f
;
1865 float max_page_scale
= 4.f
;
1866 base::TimeTicks start_time
= base::TimeTicks() +
1867 base::TimeDelta::FromSeconds(1);
1868 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1869 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1870 base::TimeTicks end_time
= start_time
+ duration
;
1872 BeginFrameArgs begin_frame_args
=
1873 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1875 // Anchor zoom with unchanged page scale should not change scroll or scale.
1877 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1879 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1881 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1882 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1887 host_impl_
->ActivateSyncTree();
1888 begin_frame_args
.frame_time
= start_time
;
1889 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1890 host_impl_
->Animate();
1891 host_impl_
->DidFinishImplFrame();
1893 begin_frame_args
.frame_time
= halfway_through_animation
;
1894 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1895 host_impl_
->Animate();
1896 EXPECT_TRUE(did_request_redraw_
);
1897 host_impl_
->DidFinishImplFrame();
1899 begin_frame_args
.frame_time
= end_time
;
1900 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1901 host_impl_
->Animate();
1902 EXPECT_TRUE(did_request_commit_
);
1903 host_impl_
->DidFinishImplFrame();
1905 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1906 host_impl_
->ProcessScrollDeltas();
1907 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1908 ExpectNone(*scroll_info
, scroll_layer
->id());
1912 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1913 host_impl_
->CreatePendingTree();
1914 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
1915 CreateScrollAndContentsLayers(
1916 host_impl_
->pending_tree(),
1917 gfx::Size(100, 100));
1918 host_impl_
->ActivateSyncTree();
1921 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1922 DCHECK(scroll_layer
);
1924 float min_page_scale
= 0.5f
;
1925 float max_page_scale
= 4.f
;
1926 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1928 host_impl_
->ActivateSyncTree();
1930 base::TimeTicks start_time
= base::TimeTicks() +
1931 base::TimeDelta::FromSeconds(1);
1932 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1933 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1934 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1935 base::TimeTicks end_time
= start_time
+ duration
;
1936 float target_scale
= 2.f
;
1938 BeginFrameArgs begin_frame_args
=
1939 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1941 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1943 // Make sure TakePageScaleAnimation works properly.
1945 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1946 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1951 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1952 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1953 EXPECT_EQ(target_scale
, psa
->scale
);
1954 EXPECT_EQ(duration
, psa
->duration
);
1955 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1957 // Recreate the PSA. Nothing should happen here since the tree containing the
1958 // PSA hasn't been activated yet.
1959 did_request_redraw_
= false;
1960 did_request_animate_
= false;
1961 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1962 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1967 begin_frame_args
.frame_time
= halfway_through_animation
;
1968 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1969 host_impl_
->Animate();
1970 EXPECT_FALSE(did_request_animate_
);
1971 EXPECT_FALSE(did_request_redraw_
);
1972 host_impl_
->DidFinishImplFrame();
1974 // Activate the sync tree. This should cause the animation to become enabled.
1975 // It should also clear the pointer on the sync tree.
1976 host_impl_
->ActivateSyncTree();
1978 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1979 EXPECT_FALSE(did_request_redraw_
);
1980 EXPECT_TRUE(did_request_animate_
);
1982 start_time
+= base::TimeDelta::FromSeconds(10);
1983 third_through_animation
+= base::TimeDelta::FromSeconds(10);
1984 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1985 end_time
+= base::TimeDelta::FromSeconds(10);
1987 // From here on, make sure the animation runs as normal.
1988 did_request_redraw_
= false;
1989 did_request_animate_
= false;
1990 begin_frame_args
.frame_time
= start_time
;
1991 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1992 host_impl_
->Animate();
1993 EXPECT_TRUE(did_request_redraw_
);
1994 EXPECT_TRUE(did_request_animate_
);
1995 host_impl_
->DidFinishImplFrame();
1997 did_request_redraw_
= false;
1998 did_request_animate_
= false;
1999 begin_frame_args
.frame_time
= third_through_animation
;
2000 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2001 host_impl_
->Animate();
2002 EXPECT_TRUE(did_request_redraw_
);
2003 EXPECT_TRUE(did_request_animate_
);
2004 host_impl_
->DidFinishImplFrame();
2006 // Another activation shouldn't have any effect on the animation.
2007 host_impl_
->ActivateSyncTree();
2009 did_request_redraw_
= false;
2010 did_request_animate_
= false;
2011 begin_frame_args
.frame_time
= halfway_through_animation
;
2012 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2013 host_impl_
->Animate();
2014 EXPECT_TRUE(did_request_redraw_
);
2015 EXPECT_TRUE(did_request_animate_
);
2016 host_impl_
->DidFinishImplFrame();
2018 did_request_redraw_
= false;
2019 did_request_animate_
= false;
2020 did_request_commit_
= false;
2021 begin_frame_args
.frame_time
= end_time
;
2022 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2023 host_impl_
->Animate();
2024 EXPECT_TRUE(did_request_commit_
);
2025 EXPECT_FALSE(did_request_animate_
);
2026 host_impl_
->DidFinishImplFrame();
2028 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
2029 host_impl_
->ProcessScrollDeltas();
2030 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
2031 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
2032 gfx::Vector2d(-50, -50)));
2035 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
2036 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2037 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2040 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
2041 DCHECK(scroll_layer
);
2043 base::TimeTicks start_time
=
2044 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
2045 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
2046 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
2047 base::TimeTicks end_time
= start_time
+ duration
;
2049 BeginFrameArgs begin_frame_args
=
2050 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
2052 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2053 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
2055 did_complete_page_scale_animation_
= false;
2056 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
2057 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
2058 gfx::Vector2d(), false, 2.f
, duration
)));
2059 host_impl_
->ActivateSyncTree();
2060 begin_frame_args
.frame_time
= start_time
;
2061 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2062 host_impl_
->Animate();
2063 EXPECT_FALSE(did_complete_page_scale_animation_
);
2064 host_impl_
->DidFinishImplFrame();
2066 begin_frame_args
.frame_time
= halfway_through_animation
;
2067 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2068 host_impl_
->Animate();
2069 EXPECT_FALSE(did_complete_page_scale_animation_
);
2070 host_impl_
->DidFinishImplFrame();
2072 begin_frame_args
.frame_time
= end_time
;
2073 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2074 host_impl_
->Animate();
2075 EXPECT_TRUE(did_complete_page_scale_animation_
);
2076 host_impl_
->DidFinishImplFrame();
2079 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
2081 LayerTreeHostImplOverridePhysicalTime(
2082 const LayerTreeSettings
& settings
,
2083 LayerTreeHostImplClient
* client
,
2085 SharedBitmapManager
* manager
,
2086 TaskGraphRunner
* task_graph_runner
,
2087 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
2088 : LayerTreeHostImpl(settings
,
2091 rendering_stats_instrumentation
,
2097 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
2098 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
2099 fake_current_physical_time_
);
2102 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
2103 fake_current_physical_time_
= fake_now
;
2107 base::TimeTicks fake_current_physical_time_
;
2110 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
2112 void SetupLayers(LayerTreeSettings settings
) {
2113 gfx::Size
content_size(100, 100);
2115 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
2116 new LayerTreeHostImplOverridePhysicalTime(
2117 settings
, this, &proxy_
, &shared_bitmap_manager_
,
2118 &task_graph_runner_
, &stats_instrumentation_
);
2119 host_impl_
= make_scoped_ptr(host_impl_override_time
);
2120 host_impl_
->InitializeRenderer(CreateOutputSurface());
2122 SetupScrollAndContentsLayers(content_size
);
2123 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2124 host_impl_
->SetViewportSize(
2125 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
2127 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
2128 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 400,
2129 VERTICAL
, 10, 0, false, true);
2130 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
2132 LayerImpl
* scroll
= host_impl_
->InnerViewportScrollLayer();
2133 LayerImpl
* root
= scroll
->parent()->parent();
2134 scrollbar
->SetScrollLayerAndClipLayerByIds(scroll
->id(), root
->id());
2135 root
->AddChild(scrollbar
.Pass());
2137 host_impl_
->active_tree()->DidBecomeActive();
2141 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
2142 LayerTreeSettings settings
;
2143 settings
.scrollbar_animator
= animator
;
2144 settings
.scrollbar_fade_delay_ms
= 20;
2145 settings
.scrollbar_fade_duration_ms
= 20;
2147 SetupLayers(settings
);
2149 base::TimeTicks fake_now
= base::TimeTicks::Now();
2151 EXPECT_FALSE(did_request_animate_
);
2152 EXPECT_FALSE(did_request_redraw_
);
2153 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2154 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2156 // If no scroll happened during a scroll gesture, it should have no effect.
2157 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2158 host_impl_
->ScrollEnd();
2159 EXPECT_FALSE(did_request_animate_
);
2160 EXPECT_FALSE(did_request_redraw_
);
2161 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2162 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2164 // After a scroll, a scrollbar animation should be scheduled about 20ms from
2166 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2167 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2168 EXPECT_FALSE(did_request_animate_
);
2169 EXPECT_TRUE(did_request_redraw_
);
2170 did_request_redraw_
= false;
2171 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2172 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2174 host_impl_
->ScrollEnd();
2175 EXPECT_FALSE(did_request_animate_
);
2176 EXPECT_FALSE(did_request_redraw_
);
2177 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2178 requested_animation_delay_
);
2179 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2181 fake_now
+= requested_animation_delay_
;
2182 requested_animation_delay_
= base::TimeDelta();
2183 animation_task_
.Run();
2184 animation_task_
= base::Closure();
2185 EXPECT_TRUE(did_request_animate_
);
2186 did_request_animate_
= false;
2187 EXPECT_FALSE(did_request_redraw_
);
2189 // After the scrollbar animation begins, we should start getting redraws.
2190 BeginFrameArgs begin_frame_args
=
2191 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, fake_now
);
2192 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2193 host_impl_
->Animate();
2194 EXPECT_TRUE(did_request_animate_
);
2195 did_request_animate_
= false;
2196 EXPECT_TRUE(did_request_redraw_
);
2197 did_request_redraw_
= false;
2198 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2199 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2200 host_impl_
->DidFinishImplFrame();
2202 // Setting the scroll offset outside a scroll should also cause the
2203 // scrollbar to appear and to schedule a scrollbar animation.
2204 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2205 gfx::ScrollOffset(5, 5));
2206 EXPECT_FALSE(did_request_animate_
);
2207 EXPECT_FALSE(did_request_redraw_
);
2208 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2209 requested_animation_delay_
);
2210 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2211 requested_animation_delay_
= base::TimeDelta();
2212 animation_task_
= base::Closure();
2214 // Scrollbar animation is not triggered unnecessarily.
2215 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2216 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2217 EXPECT_FALSE(did_request_animate_
);
2218 EXPECT_TRUE(did_request_redraw_
);
2219 did_request_redraw_
= false;
2220 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2221 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2223 host_impl_
->ScrollEnd();
2224 EXPECT_FALSE(did_request_animate_
);
2225 EXPECT_FALSE(did_request_redraw_
);
2226 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2227 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2229 // Changing page scale triggers scrollbar animation.
2230 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2231 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.1f
);
2232 EXPECT_FALSE(did_request_animate_
);
2233 EXPECT_FALSE(did_request_redraw_
);
2234 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2235 requested_animation_delay_
);
2236 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2237 requested_animation_delay_
= base::TimeDelta();
2238 animation_task_
= base::Closure();
2242 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
2243 RunTest(LayerTreeSettings::LINEAR_FADE
);
2246 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
2247 RunTest(LayerTreeSettings::THINNING
);
2250 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2251 float device_scale_factor
) {
2252 LayerTreeSettings settings
;
2253 settings
.scrollbar_fade_delay_ms
= 500;
2254 settings
.scrollbar_fade_duration_ms
= 300;
2255 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
2257 gfx::Size
viewport_size(300, 200);
2258 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
2259 gfx::ScaleSize(viewport_size
, device_scale_factor
));
2260 gfx::Size
content_size(1000, 1000);
2262 CreateHostImpl(settings
, CreateOutputSurface());
2263 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
2264 host_impl_
->SetViewportSize(device_viewport_size
);
2266 scoped_ptr
<LayerImpl
> root
=
2267 LayerImpl::Create(host_impl_
->active_tree(), 1);
2268 root
->SetBounds(viewport_size
);
2269 root
->SetHasRenderSurface(true);
2271 scoped_ptr
<LayerImpl
> scroll
=
2272 LayerImpl::Create(host_impl_
->active_tree(), 2);
2273 scroll
->SetScrollClipLayer(root
->id());
2274 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2275 scroll
->SetBounds(content_size
);
2276 scroll
->SetIsContainerForFixedPositionLayers(true);
2278 scoped_ptr
<LayerImpl
> contents
=
2279 LayerImpl::Create(host_impl_
->active_tree(), 3);
2280 contents
->SetDrawsContent(true);
2281 contents
->SetBounds(content_size
);
2283 // The scrollbar is on the right side.
2284 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
2285 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
2286 scrollbar
->SetDrawsContent(true);
2287 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
2288 scrollbar
->SetPosition(gfx::Point(285, 0));
2290 scroll
->AddChild(contents
.Pass());
2291 root
->AddChild(scroll
.Pass());
2292 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
2293 root
->AddChild(scrollbar
.Pass());
2295 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2296 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
2298 host_impl_
->active_tree()->DidBecomeActive();
2301 LayerImpl
* root_scroll
=
2302 host_impl_
->active_tree()->InnerViewportScrollLayer();
2303 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
2304 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
2305 static_cast<ScrollbarAnimationControllerThinning
*>(
2306 root_scroll
->scrollbar_animation_controller());
2307 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
2309 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
2310 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2312 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
2313 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2315 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2316 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2318 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
2319 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2320 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2322 did_request_redraw_
= false;
2323 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2324 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
2325 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2326 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
2327 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2328 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
2329 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2332 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
2333 SetupMouseMoveAtWithDeviceScale(1.f
);
2336 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
2337 SetupMouseMoveAtWithDeviceScale(2.f
);
2340 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
2341 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2342 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2343 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2346 CompositorFrameMetadata metadata
=
2347 host_impl_
->MakeCompositorFrameMetadata();
2348 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
2349 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
2350 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
2351 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2352 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2353 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2354 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2355 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2358 // Scrolling should update metadata immediately.
2359 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2360 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2361 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2363 CompositorFrameMetadata metadata
=
2364 host_impl_
->MakeCompositorFrameMetadata();
2365 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2367 host_impl_
->ScrollEnd();
2369 CompositorFrameMetadata metadata
=
2370 host_impl_
->MakeCompositorFrameMetadata();
2371 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2374 // Root "overflow: hidden" properties should be reflected on the outer
2375 // viewport scroll layer.
2377 host_impl_
->active_tree()
2378 ->OuterViewportScrollLayer()
2379 ->set_user_scrollable_horizontal(false);
2380 CompositorFrameMetadata metadata
=
2381 host_impl_
->MakeCompositorFrameMetadata();
2382 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2383 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2385 host_impl_
->active_tree()
2386 ->OuterViewportScrollLayer()
2387 ->set_user_scrollable_vertical(false);
2388 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2389 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2390 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2393 // Re-enable scrollability and verify that overflows are no longer hidden.
2395 host_impl_
->active_tree()
2396 ->OuterViewportScrollLayer()
2397 ->set_user_scrollable_horizontal(true);
2398 host_impl_
->active_tree()
2399 ->OuterViewportScrollLayer()
2400 ->set_user_scrollable_vertical(true);
2401 CompositorFrameMetadata metadata
=
2402 host_impl_
->MakeCompositorFrameMetadata();
2403 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2404 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2407 // Root "overflow: hidden" properties should also be reflected on the
2408 // inner viewport scroll layer.
2410 host_impl_
->active_tree()
2411 ->InnerViewportScrollLayer()
2412 ->set_user_scrollable_horizontal(false);
2413 CompositorFrameMetadata metadata
=
2414 host_impl_
->MakeCompositorFrameMetadata();
2415 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2416 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2418 host_impl_
->active_tree()
2419 ->InnerViewportScrollLayer()
2420 ->set_user_scrollable_vertical(false);
2421 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2422 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2423 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2426 // Page scale should update metadata correctly (shrinking only the viewport).
2427 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
2428 host_impl_
->PinchGestureBegin();
2429 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
2430 host_impl_
->PinchGestureEnd();
2431 host_impl_
->ScrollEnd();
2433 CompositorFrameMetadata metadata
=
2434 host_impl_
->MakeCompositorFrameMetadata();
2435 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2436 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
2437 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
2438 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2439 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2440 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2443 // Likewise if set from the main thread.
2444 host_impl_
->ProcessScrollDeltas();
2445 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
2446 host_impl_
->active_tree()->SetPageScaleOnActiveTree(4.f
);
2448 CompositorFrameMetadata metadata
=
2449 host_impl_
->MakeCompositorFrameMetadata();
2450 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2451 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
2452 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
2453 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2454 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2455 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2459 class DidDrawCheckLayer
: public LayerImpl
{
2461 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2462 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2465 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2466 will_draw_called_
= true;
2467 if (will_draw_returns_false_
)
2469 return LayerImpl::WillDraw(draw_mode
, provider
);
2472 void AppendQuads(RenderPass
* render_pass
,
2473 AppendQuadsData
* append_quads_data
) override
{
2474 append_quads_called_
= true;
2475 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2478 void DidDraw(ResourceProvider
* provider
) override
{
2479 did_draw_called_
= true;
2480 LayerImpl::DidDraw(provider
);
2483 bool will_draw_called() const { return will_draw_called_
; }
2484 bool append_quads_called() const { return append_quads_called_
; }
2485 bool did_draw_called() const { return did_draw_called_
; }
2487 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2489 void ClearDidDrawCheck() {
2490 will_draw_called_
= false;
2491 append_quads_called_
= false;
2492 did_draw_called_
= false;
2495 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2497 void AddCopyRequest() {
2498 ScopedPtrVector
<CopyOutputRequest
> requests
;
2500 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2501 SetHasRenderSurface(true);
2502 PassCopyRequests(&requests
);
2506 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2507 : LayerImpl(tree_impl
, id
),
2508 will_draw_returns_false_(false),
2509 will_draw_called_(false),
2510 append_quads_called_(false),
2511 did_draw_called_(false) {
2512 SetBounds(gfx::Size(10, 10));
2513 SetDrawsContent(true);
2514 draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
2518 bool will_draw_returns_false_
;
2519 bool will_draw_called_
;
2520 bool append_quads_called_
;
2521 bool did_draw_called_
;
2524 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2525 // The root layer is always drawn, so run this test on a child layer that
2526 // will be masked out by the root layer's bounds.
2527 host_impl_
->active_tree()->SetRootLayer(
2528 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2529 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2530 host_impl_
->active_tree()->root_layer());
2532 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2533 root
->SetHasRenderSurface(true);
2534 DidDrawCheckLayer
* layer
=
2535 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2538 LayerTreeHostImpl::FrameData frame
;
2539 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2540 host_impl_
->DrawLayers(&frame
);
2541 host_impl_
->DidDrawAllLayers(frame
);
2543 EXPECT_TRUE(layer
->will_draw_called());
2544 EXPECT_TRUE(layer
->append_quads_called());
2545 EXPECT_TRUE(layer
->did_draw_called());
2548 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2551 LayerTreeHostImpl::FrameData frame
;
2553 layer
->set_will_draw_returns_false();
2554 layer
->ClearDidDrawCheck();
2556 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2557 host_impl_
->DrawLayers(&frame
);
2558 host_impl_
->DidDrawAllLayers(frame
);
2560 EXPECT_TRUE(layer
->will_draw_called());
2561 EXPECT_FALSE(layer
->append_quads_called());
2562 EXPECT_FALSE(layer
->did_draw_called());
2566 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2567 // The root layer is always drawn, so run this test on a child layer that
2568 // will be masked out by the root layer's bounds.
2569 host_impl_
->active_tree()->SetRootLayer(
2570 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2571 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2572 host_impl_
->active_tree()->root_layer());
2573 root
->SetMasksToBounds(true);
2574 root
->SetHasRenderSurface(true);
2575 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2576 DidDrawCheckLayer
* layer
=
2577 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2578 // Ensure visible_layer_rect for layer is empty.
2579 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2580 layer
->SetBounds(gfx::Size(10, 10));
2582 LayerTreeHostImpl::FrameData frame
;
2584 EXPECT_FALSE(layer
->will_draw_called());
2585 EXPECT_FALSE(layer
->did_draw_called());
2587 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
2588 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2589 host_impl_
->DrawLayers(&frame
);
2590 host_impl_
->DidDrawAllLayers(frame
);
2592 EXPECT_FALSE(layer
->will_draw_called());
2593 EXPECT_FALSE(layer
->did_draw_called());
2595 EXPECT_TRUE(layer
->visible_layer_rect().IsEmpty());
2597 // Ensure visible_layer_rect for layer is not empty
2598 layer
->SetPosition(gfx::PointF());
2600 EXPECT_FALSE(layer
->will_draw_called());
2601 EXPECT_FALSE(layer
->did_draw_called());
2603 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2604 host_impl_
->DrawLayers(&frame
);
2605 host_impl_
->DidDrawAllLayers(frame
);
2607 EXPECT_TRUE(layer
->will_draw_called());
2608 EXPECT_TRUE(layer
->did_draw_called());
2610 EXPECT_FALSE(layer
->visible_layer_rect().IsEmpty());
2613 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2614 gfx::Size
big_size(1000, 1000);
2615 host_impl_
->SetViewportSize(big_size
);
2617 host_impl_
->active_tree()->SetRootLayer(
2618 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2619 DidDrawCheckLayer
* root
=
2620 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2622 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2623 DidDrawCheckLayer
* occluded_layer
=
2624 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2626 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2627 root
->SetHasRenderSurface(true);
2628 DidDrawCheckLayer
* top_layer
=
2629 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2630 // This layer covers the occluded_layer above. Make this layer large so it can
2632 top_layer
->SetBounds(big_size
);
2633 top_layer
->SetContentsOpaque(true);
2635 LayerTreeHostImpl::FrameData frame
;
2637 EXPECT_FALSE(occluded_layer
->will_draw_called());
2638 EXPECT_FALSE(occluded_layer
->did_draw_called());
2639 EXPECT_FALSE(top_layer
->will_draw_called());
2640 EXPECT_FALSE(top_layer
->did_draw_called());
2642 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2643 host_impl_
->DrawLayers(&frame
);
2644 host_impl_
->DidDrawAllLayers(frame
);
2646 EXPECT_FALSE(occluded_layer
->will_draw_called());
2647 EXPECT_FALSE(occluded_layer
->did_draw_called());
2648 EXPECT_TRUE(top_layer
->will_draw_called());
2649 EXPECT_TRUE(top_layer
->did_draw_called());
2652 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2653 host_impl_
->active_tree()->SetRootLayer(
2654 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2655 DidDrawCheckLayer
* root
=
2656 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2658 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2659 root
->SetHasRenderSurface(true);
2660 DidDrawCheckLayer
* layer1
=
2661 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2663 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2664 DidDrawCheckLayer
* layer2
=
2665 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2667 layer1
->SetHasRenderSurface(true);
2668 layer1
->SetShouldFlattenTransform(true);
2670 EXPECT_FALSE(root
->did_draw_called());
2671 EXPECT_FALSE(layer1
->did_draw_called());
2672 EXPECT_FALSE(layer2
->did_draw_called());
2674 LayerTreeHostImpl::FrameData frame
;
2675 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2676 host_impl_
->active_tree()->root_layer());
2677 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2678 host_impl_
->DrawLayers(&frame
);
2679 host_impl_
->DidDrawAllLayers(frame
);
2681 EXPECT_TRUE(root
->did_draw_called());
2682 EXPECT_TRUE(layer1
->did_draw_called());
2683 EXPECT_TRUE(layer2
->did_draw_called());
2685 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2686 EXPECT_TRUE(layer1
->render_surface());
2689 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2691 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2694 bool had_incomplete_tile
,
2696 ResourceProvider
* resource_provider
) {
2697 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2700 had_incomplete_tile
,
2702 resource_provider
));
2705 void AppendQuads(RenderPass
* render_pass
,
2706 AppendQuadsData
* append_quads_data
) override
{
2707 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2708 if (had_incomplete_tile_
)
2709 append_quads_data
->num_incomplete_tiles
++;
2711 append_quads_data
->num_missing_tiles
++;
2715 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2718 bool had_incomplete_tile
,
2720 ResourceProvider
* resource_provider
)
2721 : DidDrawCheckLayer(tree_impl
, id
),
2722 tile_missing_(tile_missing
),
2723 had_incomplete_tile_(had_incomplete_tile
) {
2725 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2729 bool had_incomplete_tile_
;
2732 struct PrepareToDrawSuccessTestCase
{
2734 bool has_missing_tile
= false;
2735 bool has_incomplete_tile
= false;
2736 bool is_animating
= false;
2737 bool has_copy_request
= false;
2739 bool high_res_required
= false;
2741 State layer_between
;
2743 DrawResult expected_result
;
2745 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2746 : expected_result(result
) {}
2749 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2750 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2753 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2754 // 1. Animated layer first.
2755 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2756 cases
.back().layer_before
.is_animating
= true;
2757 // 2. Animated layer between.
2758 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2759 cases
.back().layer_between
.is_animating
= true;
2760 // 3. Animated layer last.
2761 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2762 cases
.back().layer_after
.is_animating
= true;
2763 // 4. Missing tile first.
2764 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2765 cases
.back().layer_before
.has_missing_tile
= true;
2766 // 5. Missing tile between.
2767 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2768 cases
.back().layer_between
.has_missing_tile
= true;
2769 // 6. Missing tile last.
2770 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2771 cases
.back().layer_after
.has_missing_tile
= true;
2772 // 7. Incomplete tile first.
2773 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2774 cases
.back().layer_before
.has_incomplete_tile
= true;
2775 // 8. Incomplete tile between.
2776 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2777 cases
.back().layer_between
.has_incomplete_tile
= true;
2778 // 9. Incomplete tile last.
2779 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2780 cases
.back().layer_after
.has_incomplete_tile
= true;
2781 // 10. Animation with missing tile.
2783 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2784 cases
.back().layer_between
.has_missing_tile
= true;
2785 cases
.back().layer_between
.is_animating
= true;
2786 // 11. Animation with incomplete tile.
2787 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2788 cases
.back().layer_between
.has_incomplete_tile
= true;
2789 cases
.back().layer_between
.is_animating
= true;
2791 // 12. High res required.
2792 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2793 cases
.back().high_res_required
= true;
2794 // 13. High res required with incomplete tile.
2796 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2797 cases
.back().high_res_required
= true;
2798 cases
.back().layer_between
.has_incomplete_tile
= true;
2799 // 14. High res required with missing tile.
2801 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2802 cases
.back().high_res_required
= true;
2803 cases
.back().layer_between
.has_missing_tile
= true;
2805 // 15. High res required is higher priority than animating missing tiles.
2807 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2808 cases
.back().high_res_required
= true;
2809 cases
.back().layer_between
.has_missing_tile
= true;
2810 cases
.back().layer_after
.has_missing_tile
= true;
2811 cases
.back().layer_after
.is_animating
= true;
2812 // 16. High res required is higher priority than animating missing tiles.
2814 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2815 cases
.back().high_res_required
= true;
2816 cases
.back().layer_between
.has_missing_tile
= true;
2817 cases
.back().layer_before
.has_missing_tile
= true;
2818 cases
.back().layer_before
.is_animating
= true;
2820 host_impl_
->active_tree()->SetRootLayer(
2821 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2822 DidDrawCheckLayer
* root
=
2823 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2824 root
->SetHasRenderSurface(true);
2826 LayerTreeHostImpl::FrameData frame
;
2827 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2828 host_impl_
->DrawLayers(&frame
);
2829 host_impl_
->DidDrawAllLayers(frame
);
2830 host_impl_
->SwapBuffers(frame
);
2832 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2833 const auto& testcase
= cases
[i
];
2834 std::vector
<LayerImpl
*> to_remove
;
2835 for (auto* child
: root
->children())
2836 to_remove
.push_back(child
);
2837 for (auto* child
: to_remove
)
2838 root
->RemoveChild(child
);
2840 std::ostringstream scope
;
2841 scope
<< "Test case: " << i
;
2842 SCOPED_TRACE(scope
.str());
2844 root
->AddChild(MissingTextureAnimatingLayer::Create(
2845 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2846 testcase
.layer_before
.has_incomplete_tile
,
2847 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2848 DidDrawCheckLayer
* before
=
2849 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2850 if (testcase
.layer_before
.has_copy_request
)
2851 before
->AddCopyRequest();
2853 root
->AddChild(MissingTextureAnimatingLayer::Create(
2854 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2855 testcase
.layer_between
.has_incomplete_tile
,
2856 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2857 DidDrawCheckLayer
* between
=
2858 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2859 if (testcase
.layer_between
.has_copy_request
)
2860 between
->AddCopyRequest();
2862 root
->AddChild(MissingTextureAnimatingLayer::Create(
2863 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2864 testcase
.layer_after
.has_incomplete_tile
,
2865 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2866 DidDrawCheckLayer
* after
=
2867 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2868 if (testcase
.layer_after
.has_copy_request
)
2869 after
->AddCopyRequest();
2871 if (testcase
.high_res_required
)
2872 host_impl_
->SetRequiresHighResToDraw();
2874 LayerTreeHostImpl::FrameData frame
;
2875 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2876 host_impl_
->DrawLayers(&frame
);
2877 host_impl_
->DidDrawAllLayers(frame
);
2878 host_impl_
->SwapBuffers(frame
);
2882 TEST_F(LayerTreeHostImplTest
,
2883 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2884 CreateHostImpl(DefaultSettings(),
2885 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2886 EXPECT_TRUE(host_impl_
->output_surface()
2888 .draw_and_swap_full_viewport_every_frame
);
2890 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2893 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2894 // 1. Animation with missing tile.
2895 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2896 cases
.back().layer_between
.has_missing_tile
= true;
2897 cases
.back().layer_between
.is_animating
= true;
2898 // 2. High res required with incomplete tile.
2899 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2900 cases
.back().high_res_required
= true;
2901 cases
.back().layer_between
.has_incomplete_tile
= true;
2902 // 3. High res required with missing tile.
2903 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2904 cases
.back().high_res_required
= true;
2905 cases
.back().layer_between
.has_missing_tile
= true;
2907 host_impl_
->active_tree()->SetRootLayer(
2908 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2909 DidDrawCheckLayer
* root
=
2910 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2911 root
->SetHasRenderSurface(true);
2913 LayerTreeHostImpl::FrameData frame
;
2914 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2915 host_impl_
->DrawLayers(&frame
);
2916 host_impl_
->DidDrawAllLayers(frame
);
2917 host_impl_
->SwapBuffers(frame
);
2919 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2920 const auto& testcase
= cases
[i
];
2921 std::vector
<LayerImpl
*> to_remove
;
2922 for (auto* child
: root
->children())
2923 to_remove
.push_back(child
);
2924 for (auto* child
: to_remove
)
2925 root
->RemoveChild(child
);
2927 std::ostringstream scope
;
2928 scope
<< "Test case: " << i
;
2929 SCOPED_TRACE(scope
.str());
2931 root
->AddChild(MissingTextureAnimatingLayer::Create(
2932 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2933 testcase
.layer_before
.has_incomplete_tile
,
2934 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2935 DidDrawCheckLayer
* before
=
2936 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2937 if (testcase
.layer_before
.has_copy_request
)
2938 before
->AddCopyRequest();
2940 root
->AddChild(MissingTextureAnimatingLayer::Create(
2941 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2942 testcase
.layer_between
.has_incomplete_tile
,
2943 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2944 DidDrawCheckLayer
* between
=
2945 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2946 if (testcase
.layer_between
.has_copy_request
)
2947 between
->AddCopyRequest();
2949 root
->AddChild(MissingTextureAnimatingLayer::Create(
2950 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2951 testcase
.layer_after
.has_incomplete_tile
,
2952 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2953 DidDrawCheckLayer
* after
=
2954 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2955 if (testcase
.layer_after
.has_copy_request
)
2956 after
->AddCopyRequest();
2958 if (testcase
.high_res_required
)
2959 host_impl_
->SetRequiresHighResToDraw();
2961 LayerTreeHostImpl::FrameData frame
;
2962 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2963 host_impl_
->DrawLayers(&frame
);
2964 host_impl_
->DidDrawAllLayers(frame
);
2965 host_impl_
->SwapBuffers(frame
);
2969 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2970 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2971 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2972 root
->SetHasRenderSurface(true);
2973 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2976 // Scroll event is ignored because layer is not scrollable.
2977 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2978 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2979 EXPECT_FALSE(did_request_redraw_
);
2980 EXPECT_FALSE(did_request_commit_
);
2983 TEST_F(LayerTreeHostImplTest
, ClampingAfterActivation
) {
2984 host_impl_
->CreatePendingTree();
2985 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2986 CreateScrollAndContentsLayers(host_impl_
->pending_tree(),
2987 gfx::Size(100, 100));
2988 host_impl_
->ActivateSyncTree();
2990 host_impl_
->CreatePendingTree();
2991 const gfx::ScrollOffset pending_scroll
= gfx::ScrollOffset(-100, -100);
2992 LayerImpl
* active_outer_layer
=
2993 host_impl_
->active_tree()->OuterViewportScrollLayer();
2994 LayerImpl
* pending_outer_layer
=
2995 host_impl_
->pending_tree()->OuterViewportScrollLayer();
2996 pending_outer_layer
->PushScrollOffsetFromMainThread(pending_scroll
);
2998 host_impl_
->ActivateSyncTree();
2999 // Scrolloffsets on the active tree will be clamped after activation.
3000 EXPECT_EQ(active_outer_layer
->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
3003 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
3005 LayerTreeHostImplTopControlsTest()
3006 // Make the clip size the same as the layer (content) size so the layer is
3008 : layer_size_(10, 10),
3009 clip_size_(layer_size_
),
3010 top_controls_height_(50) {
3011 viewport_size_
= gfx::Size(clip_size_
.width(),
3012 clip_size_
.height() + top_controls_height_
);
3015 bool CreateHostImpl(const LayerTreeSettings
& settings
,
3016 scoped_ptr
<OutputSurface
> output_surface
) override
{
3018 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
3020 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
3021 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3022 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
3027 void SetupTopControlsAndScrollLayerWithVirtualViewport(
3028 const gfx::Size
& inner_viewport_size
,
3029 const gfx::Size
& outer_viewport_size
,
3030 const gfx::Size
& scroll_layer_size
) {
3031 CreateHostImpl(settings_
, CreateOutputSurface());
3032 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3033 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
3034 host_impl_
->DidChangeTopControlsPosition();
3036 scoped_ptr
<LayerImpl
> root
=
3037 LayerImpl::Create(host_impl_
->active_tree(), 1);
3038 scoped_ptr
<LayerImpl
> root_clip
=
3039 LayerImpl::Create(host_impl_
->active_tree(), 2);
3040 scoped_ptr
<LayerImpl
> page_scale
=
3041 LayerImpl::Create(host_impl_
->active_tree(), 3);
3043 scoped_ptr
<LayerImpl
> outer_scroll
=
3044 LayerImpl::Create(host_impl_
->active_tree(), 4);
3045 scoped_ptr
<LayerImpl
> outer_clip
=
3046 LayerImpl::Create(host_impl_
->active_tree(), 5);
3048 root_clip
->SetBounds(inner_viewport_size
);
3049 root
->SetScrollClipLayer(root_clip
->id());
3050 root
->SetBounds(outer_viewport_size
);
3051 root
->SetPosition(gfx::PointF());
3052 root
->SetDrawsContent(false);
3053 root
->SetIsContainerForFixedPositionLayers(true);
3054 root_clip
->SetHasRenderSurface(true);
3055 outer_clip
->SetBounds(outer_viewport_size
);
3056 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
3057 outer_scroll
->SetBounds(scroll_layer_size
);
3058 outer_scroll
->SetPosition(gfx::PointF());
3059 outer_scroll
->SetDrawsContent(false);
3060 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
3062 int inner_viewport_scroll_layer_id
= root
->id();
3063 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
3064 int page_scale_layer_id
= page_scale
->id();
3066 outer_clip
->AddChild(outer_scroll
.Pass());
3067 root
->AddChild(outer_clip
.Pass());
3068 page_scale
->AddChild(root
.Pass());
3069 root_clip
->AddChild(page_scale
.Pass());
3071 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3072 host_impl_
->active_tree()->SetViewportLayersFromIds(
3073 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
3074 outer_viewport_scroll_layer_id
);
3076 host_impl_
->SetViewportSize(inner_viewport_size
);
3077 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3078 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
3082 gfx::Size layer_size_
;
3083 gfx::Size clip_size_
;
3084 gfx::Size viewport_size_
;
3085 float top_controls_height_
;
3087 LayerTreeSettings settings_
;
3088 }; // class LayerTreeHostImplTopControlsTest
3090 // Tests that, on a page with content the same size as the viewport, hiding
3091 // the top controls also increases the ScrollableSize (i.e. the content size).
3092 // Since the viewport got larger, the effective scrollable "content" also did.
3093 // This ensures, for one thing, that the overscroll glow is shown in the right
3095 TEST_F(LayerTreeHostImplTopControlsTest
,
3096 HidingTopControlsExpandsScrollableSize
) {
3097 SetupTopControlsAndScrollLayerWithVirtualViewport(
3098 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
3100 LayerTreeImpl
* active_tree
= host_impl_
->active_tree();
3102 // Create a content layer beneath the outer viewport scroll layer.
3103 int id
= host_impl_
->OuterViewportScrollLayer()->id();
3104 host_impl_
->OuterViewportScrollLayer()->AddChild(
3105 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2));
3106 LayerImpl
* content
= active_tree
->OuterViewportScrollLayer()->children()[0];
3107 content
->SetBounds(gfx::Size(50, 50));
3111 LayerImpl
* inner_container
= active_tree
->InnerViewportContainerLayer();
3112 LayerImpl
* outer_container
= active_tree
->OuterViewportContainerLayer();
3114 // The top controls should start off showing so the viewport should be shrunk.
3115 ASSERT_EQ(gfx::Size(50, 50), inner_container
->bounds());
3116 ASSERT_EQ(gfx::Size(50, 50), outer_container
->bounds());
3118 EXPECT_EQ(gfx::SizeF(50, 50), active_tree
->ScrollableSize());
3120 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3121 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3123 host_impl_
->top_controls_manager()->ScrollBegin();
3125 // Hide the top controls by a bit, the scrollable size should increase but the
3126 // actual content bounds shouldn't.
3128 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3129 ASSERT_EQ(gfx::Size(50, 75), inner_container
->bounds());
3130 ASSERT_EQ(gfx::Size(50, 75), outer_container
->bounds());
3131 EXPECT_EQ(gfx::SizeF(50, 75), active_tree
->ScrollableSize());
3132 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3135 // Fully hide the top controls.
3137 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3138 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3139 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3140 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3141 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3144 // Scrolling additionally shouldn't have any effect.
3146 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3147 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3148 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3149 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3150 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3153 host_impl_
->top_controls_manager()->ScrollEnd();
3154 host_impl_
->ScrollEnd();
3157 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
3158 SetupTopControlsAndScrollLayerWithVirtualViewport(
3159 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
3162 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3163 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3165 // Make the test scroll delta a fractional amount, to verify that the
3166 // fixed container size delta is (1) non-zero, and (2) fractional, and
3167 // (3) matches the movement of the top controls.
3168 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
3169 host_impl_
->top_controls_manager()->ScrollBegin();
3170 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3171 host_impl_
->top_controls_manager()->ScrollEnd();
3173 LayerImpl
* inner_viewport_scroll_layer
=
3174 host_impl_
->active_tree()->InnerViewportScrollLayer();
3175 DCHECK(inner_viewport_scroll_layer
);
3176 host_impl_
->ScrollEnd();
3177 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3178 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3181 // In this test, the outer viewport is initially unscrollable. We test that a
3182 // scroll initiated on the inner viewport, causing the top controls to show and
3183 // thus making the outer viewport scrollable, still scrolls the outer viewport.
3184 TEST_F(LayerTreeHostImplTopControlsTest
,
3185 TopControlsOuterViewportBecomesScrollable
) {
3186 SetupTopControlsAndScrollLayerWithVirtualViewport(
3187 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
3190 LayerImpl
* inner_scroll
=
3191 host_impl_
->active_tree()->InnerViewportScrollLayer();
3192 LayerImpl
* inner_container
=
3193 host_impl_
->active_tree()->InnerViewportContainerLayer();
3194 LayerImpl
* outer_scroll
=
3195 host_impl_
->active_tree()->OuterViewportScrollLayer();
3196 LayerImpl
* outer_container
=
3197 host_impl_
->active_tree()->OuterViewportContainerLayer();
3199 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
3200 outer_scroll
->SetDrawsContent(true);
3201 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
3203 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3204 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3205 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
3207 // The entire scroll delta should have been used to hide the top controls.
3208 // The viewport layers should be resized back to their full sizes.
3209 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3210 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3211 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
3212 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
3214 // The inner viewport should be scrollable by 50px * page_scale.
3215 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
3216 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
3217 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3218 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
3220 host_impl_
->ScrollEnd();
3222 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3223 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3224 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
3226 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3228 // The entire scroll delta should have been used to show the top controls.
3229 // The outer viewport should be resized to accomodate and scrolled to the
3230 // bottom of the document to keep the viewport in place.
3231 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3232 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
3233 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
3234 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3235 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3237 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3238 // since it wasn't scrollable when the scroll began.
3239 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
3240 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3241 EXPECT_EQ(15.f
, inner_scroll
->CurrentScrollOffset().y());
3243 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
3244 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3245 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3247 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3248 host_impl_
->ScrollEnd();
3250 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3251 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3254 // Test that the fixed position container delta is appropriately adjusted
3255 // by the top controls showing/hiding and page scale doesn't affect it.
3256 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
3257 SetupTopControlsAndScrollLayerWithVirtualViewport(
3258 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3260 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3262 float page_scale
= 1.5f
;
3263 LayerImpl
* outer_viewport_scroll_layer
=
3264 host_impl_
->active_tree()->OuterViewportScrollLayer();
3266 // Zoom in, since the fixed container is the outer viewport, the delta should
3268 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3270 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3271 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3273 // Scroll down, the top controls hiding should expand the viewport size so
3274 // the delta should be equal to the scroll distance.
3275 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
3276 host_impl_
->top_controls_manager()->ScrollBegin();
3277 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3278 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
3279 host_impl_
->top_controls_manager()->ContentTopOffset());
3280 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3281 outer_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3282 host_impl_
->ScrollEnd();
3284 // Scroll past the maximum extent. The delta shouldn't be greater than the
3285 // top controls height.
3286 host_impl_
->top_controls_manager()->ScrollBegin();
3287 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3288 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3289 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3290 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3291 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
3292 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3293 host_impl_
->ScrollEnd();
3295 // Scroll in the direction to make the top controls show.
3296 host_impl_
->top_controls_manager()->ScrollBegin();
3297 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
3298 EXPECT_EQ(top_controls_scroll_delta
.y(),
3299 host_impl_
->top_controls_manager()->ContentTopOffset());
3301 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
3302 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3303 host_impl_
->top_controls_manager()->ScrollEnd();
3306 // Test that if only the top controls are scrolled, we shouldn't request a
3308 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsDontTriggerCommit
) {
3309 SetupTopControlsAndScrollLayerWithVirtualViewport(
3310 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3313 // Show top controls
3314 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3316 // Scroll 25px to hide top controls
3317 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3318 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3319 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3320 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3321 EXPECT_FALSE(did_request_commit_
);
3324 // Test that if a scrollable sublayer doesn't consume the scroll,
3325 // top controls should hide when scrolling down.
3326 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
3327 gfx::Size
sub_content_size(100, 400);
3328 gfx::Size
sub_content_layer_size(100, 300);
3329 SetupTopControlsAndScrollLayerWithVirtualViewport(
3330 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3333 // Show top controls
3334 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3336 LayerImpl
* outer_viewport_scroll_layer
=
3337 host_impl_
->active_tree()->OuterViewportScrollLayer();
3338 int id
= outer_viewport_scroll_layer
->id();
3340 scoped_ptr
<LayerImpl
> child
=
3341 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
3342 scoped_ptr
<LayerImpl
> child_clip
=
3343 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
3345 child_clip
->SetBounds(sub_content_layer_size
);
3346 child
->SetScrollClipLayer(child_clip
->id());
3347 child
->SetBounds(sub_content_size
);
3348 child
->SetPosition(gfx::PointF());
3349 child
->SetDrawsContent(true);
3350 child
->SetIsContainerForFixedPositionLayers(true);
3352 // scroll child to limit
3353 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
3354 child_clip
->AddChild(child
.Pass());
3355 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
3357 // Scroll 25px to hide top controls
3358 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3359 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3360 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3361 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3362 host_impl_
->ScrollEnd();
3364 // Top controls should be hidden
3365 EXPECT_EQ(scroll_delta
.y(),
3366 top_controls_height_
-
3367 host_impl_
->top_controls_manager()->ContentTopOffset());
3370 // Ensure setting the top controls position explicitly using the setters on the
3371 // TreeImpl correctly affects the top controls manager and viewport bounds.
3372 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
3373 CreateHostImpl(settings_
, CreateOutputSurface());
3374 SetupTopControlsAndScrollLayerWithVirtualViewport(
3375 layer_size_
, layer_size_
, layer_size_
);
3378 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3379 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3380 30.f
/ top_controls_height_
);
3381 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3382 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3383 EXPECT_FLOAT_EQ(-20.f
,
3384 host_impl_
->top_controls_manager()->ControlsTopOffset());
3386 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3387 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3388 EXPECT_FLOAT_EQ(-50.f
,
3389 host_impl_
->top_controls_manager()->ControlsTopOffset());
3391 host_impl_
->DidChangeTopControlsPosition();
3393 // Now that top controls have moved, expect the clip to resize.
3394 LayerImpl
* inner_clip_ptr
=
3395 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3396 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3399 // Test that the top_controls delta and sent delta are appropriately
3400 // applied on sync tree activation. The total top controls offset shouldn't
3401 // change after the activation.
3402 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
3403 CreateHostImpl(settings_
, CreateOutputSurface());
3404 SetupTopControlsAndScrollLayerWithVirtualViewport(
3405 layer_size_
, layer_size_
, layer_size_
);
3408 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3409 20.f
/ top_controls_height_
);
3410 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3411 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
3412 15.f
/ top_controls_height_
);
3413 host_impl_
->active_tree()
3414 ->top_controls_shown_ratio()
3415 ->PullDeltaForMainThread();
3416 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3417 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
3418 top_controls_height_
);
3420 host_impl_
->DidChangeTopControlsPosition();
3421 LayerImpl
* inner_clip_ptr
=
3422 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3423 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3424 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3426 host_impl_
->ActivateSyncTree();
3428 inner_clip_ptr
= host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3429 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3430 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3433 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
3434 top_controls_height_
);
3437 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3438 top_controls_height_
);
3441 // Test that changing the top controls layout height is correctly applied to
3442 // the inner viewport container bounds. That is, the top controls layout
3443 // height is the amount that the inner viewport container was shrunk outside
3444 // the compositor to accommodate the top controls.
3445 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
3446 CreateHostImpl(settings_
, CreateOutputSurface());
3447 SetupTopControlsAndScrollLayerWithVirtualViewport(
3448 layer_size_
, layer_size_
, layer_size_
);
3451 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
3452 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3454 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3456 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3457 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3459 host_impl_
->DidChangeTopControlsPosition();
3460 LayerImpl
* inner_clip_ptr
=
3461 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3462 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3463 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3465 host_impl_
->sync_tree()->root_layer()->SetBounds(
3466 gfx::Size(inner_clip_ptr
->bounds().width(),
3467 inner_clip_ptr
->bounds().height() - 50.f
));
3469 host_impl_
->ActivateSyncTree();
3472 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3473 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3475 // The total bounds should remain unchanged since the bounds delta should
3476 // account for the difference between the layout height and the current
3477 // top controls offset.
3478 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3479 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), inner_clip_ptr
->bounds_delta());
3481 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3482 host_impl_
->DidChangeTopControlsPosition();
3484 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
3485 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
3486 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3487 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), inner_clip_ptr
->bounds_delta());
3488 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
3489 inner_clip_ptr
->bounds());
3492 // Test that showing/hiding the top controls when the viewport is fully scrolled
3493 // doesn't incorrectly change the viewport offset due to clamping from changing
3495 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
3496 SetupTopControlsAndScrollLayerWithVirtualViewport(
3497 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3500 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3502 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3503 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3505 // Scroll the viewports to max scroll offset.
3506 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3507 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3509 gfx::ScrollOffset viewport_offset
=
3510 host_impl_
->active_tree()->TotalScrollOffset();
3511 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
3513 // Hide the top controls by 25px.
3514 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3515 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3516 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3517 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3519 // scrolling down at the max extents no longer hides the top controls
3520 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3522 // forcefully hide the top controls by 25px
3523 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3524 host_impl_
->ScrollEnd();
3526 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3527 top_controls_height_
-
3528 host_impl_
->top_controls_manager()->ContentTopOffset());
3530 inner_scroll
->ClampScrollToMaxScrollOffset();
3531 outer_scroll
->ClampScrollToMaxScrollOffset();
3533 // We should still be fully scrolled.
3534 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3535 host_impl_
->active_tree()->TotalScrollOffset());
3537 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3539 // Bring the top controls down by 25px.
3540 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3541 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3542 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3543 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3544 host_impl_
->ScrollEnd();
3546 // The viewport offset shouldn't have changed.
3547 EXPECT_EQ(viewport_offset
,
3548 host_impl_
->active_tree()->TotalScrollOffset());
3550 // Scroll the viewports to max scroll offset.
3551 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3552 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3553 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3554 host_impl_
->active_tree()->TotalScrollOffset());
3557 // Test that the top controls coming in and out maintains the same aspect ratio
3558 // between the inner and outer viewports.
3559 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3560 SetupTopControlsAndScrollLayerWithVirtualViewport(
3561 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3562 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 2.f
);
3565 EXPECT_FLOAT_EQ(top_controls_height_
,
3566 host_impl_
->top_controls_manager()->ContentTopOffset());
3568 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3569 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3570 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3571 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3572 host_impl_
->ScrollEnd();
3574 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3575 top_controls_height_
-
3576 host_impl_
->top_controls_manager()->ContentTopOffset());
3578 // Top controls were hidden by 25px so the inner viewport should have expanded
3580 LayerImpl
* outer_container
=
3581 host_impl_
->active_tree()->OuterViewportContainerLayer();
3582 LayerImpl
* inner_container
=
3583 host_impl_
->active_tree()->InnerViewportContainerLayer();
3584 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3586 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3587 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3588 inner_container
->BoundsForScrolling().height();
3589 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3590 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3592 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3595 // Test that scrolling the outer viewport affects the top controls.
3596 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3597 SetupTopControlsAndScrollLayerWithVirtualViewport(
3598 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3601 EXPECT_EQ(top_controls_height_
,
3602 host_impl_
->top_controls_manager()->ContentTopOffset());
3604 // Send a gesture scroll that will scroll the outer viewport, make sure the
3605 // top controls get scrolled.
3606 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3607 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3608 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3609 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3610 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3611 host_impl_
->CurrentlyScrollingLayer());
3612 host_impl_
->ScrollEnd();
3614 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3615 top_controls_height_
-
3616 host_impl_
->top_controls_manager()->ContentTopOffset());
3618 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3619 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3620 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3621 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3623 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3624 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3625 host_impl_
->CurrentlyScrollingLayer());
3627 host_impl_
->ScrollEnd();
3629 // Position the viewports such that the inner viewport will be scrolled.
3630 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3631 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3632 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3634 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3635 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3636 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3637 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3639 EXPECT_EQ(top_controls_height_
,
3640 host_impl_
->top_controls_manager()->ContentTopOffset());
3642 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3643 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3645 host_impl_
->ScrollEnd();
3648 TEST_F(LayerTreeHostImplTopControlsTest
,
3649 ScrollNonScrollableRootWithTopControls
) {
3650 CreateHostImpl(settings_
, CreateOutputSurface());
3651 SetupTopControlsAndScrollLayerWithVirtualViewport(
3652 layer_size_
, layer_size_
, layer_size_
);
3655 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3656 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3658 host_impl_
->top_controls_manager()->ScrollBegin();
3659 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3660 host_impl_
->top_controls_manager()->ScrollEnd();
3661 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3662 // Now that top controls have moved, expect the clip to resize.
3663 LayerImpl
* inner_clip_ptr
=
3664 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3665 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3667 host_impl_
->ScrollEnd();
3669 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3670 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3672 float scroll_increment_y
= -25.f
;
3673 host_impl_
->top_controls_manager()->ScrollBegin();
3674 host_impl_
->top_controls_manager()->ScrollBy(
3675 gfx::Vector2dF(0.f
, scroll_increment_y
));
3676 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3677 host_impl_
->top_controls_manager()->ContentTopOffset());
3678 // Now that top controls have moved, expect the clip to resize.
3679 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3680 viewport_size_
.height() + scroll_increment_y
),
3681 inner_clip_ptr
->bounds());
3683 host_impl_
->top_controls_manager()->ScrollBy(
3684 gfx::Vector2dF(0.f
, scroll_increment_y
));
3685 host_impl_
->top_controls_manager()->ScrollEnd();
3686 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3687 host_impl_
->top_controls_manager()->ContentTopOffset());
3688 // Now that top controls have moved, expect the clip to resize.
3689 EXPECT_EQ(clip_size_
, inner_clip_ptr
->bounds());
3691 host_impl_
->ScrollEnd();
3693 // Verify the layer is once-again non-scrollable.
3695 gfx::ScrollOffset(),
3696 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3698 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3699 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3702 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3703 // Test the configuration where a non-composited root layer is embedded in a
3704 // scrollable outer layer.
3705 gfx::Size
surface_size(10, 10);
3706 gfx::Size
contents_size(20, 20);
3708 scoped_ptr
<LayerImpl
> content_layer
=
3709 LayerImpl::Create(host_impl_
->active_tree(), 1);
3710 content_layer
->SetDrawsContent(true);
3711 content_layer
->SetPosition(gfx::PointF());
3712 content_layer
->SetBounds(contents_size
);
3714 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3715 LayerImpl::Create(host_impl_
->active_tree(), 3);
3716 scroll_clip_layer
->SetBounds(surface_size
);
3718 scoped_ptr
<LayerImpl
> scroll_layer
=
3719 LayerImpl::Create(host_impl_
->active_tree(), 2);
3720 scroll_layer
->SetScrollClipLayer(3);
3721 scroll_layer
->SetBounds(contents_size
);
3722 scroll_layer
->SetPosition(gfx::PointF());
3723 scroll_layer
->AddChild(content_layer
.Pass());
3724 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3726 scroll_clip_layer
->SetHasRenderSurface(true);
3727 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3728 host_impl_
->SetViewportSize(surface_size
);
3731 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3732 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3733 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3734 host_impl_
->ScrollEnd();
3735 EXPECT_TRUE(did_request_redraw_
);
3736 EXPECT_TRUE(did_request_commit_
);
3739 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3740 gfx::Size
surface_size(10, 10);
3741 gfx::Size
contents_size(20, 20);
3742 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3743 root
->SetBounds(surface_size
);
3744 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3745 root
->SetHasRenderSurface(true);
3746 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3747 host_impl_
->SetViewportSize(surface_size
);
3750 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3751 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3752 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3753 host_impl_
->ScrollEnd();
3754 EXPECT_TRUE(did_request_redraw_
);
3755 EXPECT_TRUE(did_request_commit_
);
3758 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3759 gfx::Size
surface_size(10, 10);
3760 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3761 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3762 root
->SetHasRenderSurface(true);
3763 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3764 host_impl_
->SetViewportSize(surface_size
);
3767 // Scroll event is ignored because the input coordinate is outside the layer
3769 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3770 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3771 EXPECT_FALSE(did_request_redraw_
);
3772 EXPECT_FALSE(did_request_commit_
);
3775 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3776 gfx::Size
surface_size(10, 10);
3777 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3778 root
->SetHasRenderSurface(true);
3779 scoped_ptr
<LayerImpl
> child
=
3780 CreateScrollableLayer(2, surface_size
, root
.get());
3781 host_impl_
->SetViewportSize(surface_size
);
3783 gfx::Transform matrix
;
3784 matrix
.RotateAboutXAxis(180.0);
3785 child
->SetTransform(matrix
);
3786 child
->SetDoubleSided(false);
3788 root
->AddChild(child
.Pass());
3789 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3792 // Scroll event is ignored because the scrollable layer is not facing the
3793 // viewer and there is nothing scrollable behind it.
3794 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3795 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3796 EXPECT_FALSE(did_request_redraw_
);
3797 EXPECT_FALSE(did_request_commit_
);
3800 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3801 gfx::Size
surface_size(10, 10);
3802 scoped_ptr
<LayerImpl
> clip_layer
=
3803 LayerImpl::Create(host_impl_
->active_tree(), 3);
3804 scoped_ptr
<LayerImpl
> content_layer
=
3805 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3806 content_layer
->SetShouldScrollOnMainThread(true);
3807 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3809 // Note: we can use the same clip layer for both since both calls to
3810 // CreateScrollableLayer() use the same surface size.
3811 scoped_ptr
<LayerImpl
> scroll_layer
=
3812 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3813 scroll_layer
->AddChild(content_layer
.Pass());
3814 clip_layer
->AddChild(scroll_layer
.Pass());
3815 clip_layer
->SetHasRenderSurface(true);
3817 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3818 host_impl_
->SetViewportSize(surface_size
);
3821 // Scrolling fails because the content layer is asking to be scrolled on the
3823 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3824 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3827 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3828 gfx::Size
viewport_size(20, 20);
3829 float page_scale
= 2.f
;
3831 SetupScrollAndContentsLayers(viewport_size
);
3833 // Setup the layers so that the outer viewport is scrollable.
3834 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3836 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3838 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3841 LayerImpl
* root_scroll
=
3842 host_impl_
->active_tree()->OuterViewportScrollLayer();
3843 LayerImpl
* inner_scroll
=
3844 host_impl_
->active_tree()->InnerViewportScrollLayer();
3845 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3847 gfx::Vector2d
scroll_delta(0, 10);
3848 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3849 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3850 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3851 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3852 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3853 host_impl_
->ScrollEnd();
3855 // Set new page scale from main thread.
3856 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3858 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3859 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3860 expected_scroll_delta
));
3862 // The scroll range should also have been updated.
3863 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3865 // The page scale delta remains constant because the impl thread did not
3867 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3870 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3871 gfx::Size
viewport_size(20, 20);
3872 float page_scale
= 2.f
;
3874 SetupScrollAndContentsLayers(viewport_size
);
3876 // Setup the layers so that the outer viewport is scrollable.
3877 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3879 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3881 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3884 LayerImpl
* root_scroll
=
3885 host_impl_
->active_tree()->OuterViewportScrollLayer();
3886 LayerImpl
* inner_scroll
=
3887 host_impl_
->active_tree()->InnerViewportScrollLayer();
3888 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3890 gfx::Vector2d
scroll_delta(0, 10);
3891 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3892 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3893 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3894 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3895 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3896 host_impl_
->ScrollEnd();
3898 // Set new page scale on impl thread by pinching.
3899 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3900 host_impl_
->PinchGestureBegin();
3901 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3902 host_impl_
->PinchGestureEnd();
3903 host_impl_
->ScrollEnd();
3906 // The scroll delta is not scaled because the main thread did not scale.
3907 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3908 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3909 expected_scroll_delta
));
3911 // The scroll range should also have been updated.
3912 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3914 // The page scale delta should match the new scale on the impl side.
3915 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3918 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3919 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3920 gfx::Size
surface_size(10, 10);
3921 float default_page_scale
= 1.f
;
3922 gfx::Transform default_page_scale_matrix
;
3923 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3925 float new_page_scale
= 2.f
;
3926 gfx::Transform new_page_scale_matrix
;
3927 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3929 // Create a normal scrollable root layer and another scrollable child layer.
3930 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3931 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3932 LayerImpl
* child
= scroll
->children()[0];
3934 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3935 LayerImpl::Create(host_impl_
->active_tree(), 6);
3936 scoped_ptr
<LayerImpl
> scrollable_child
=
3937 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3938 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3939 child
->AddChild(scrollable_child_clip
.Pass());
3940 LayerImpl
* grand_child
= child
->children()[0];
3942 // Set new page scale on impl thread by pinching.
3943 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3944 host_impl_
->PinchGestureBegin();
3945 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3946 host_impl_
->PinchGestureEnd();
3947 host_impl_
->ScrollEnd();
3950 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3951 // the page scale delta on the root layer is applied hierarchically.
3952 LayerTreeHostImpl::FrameData frame
;
3953 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3954 host_impl_
->DrawLayers(&frame
);
3955 host_impl_
->DidDrawAllLayers(frame
);
3957 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3958 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3959 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3960 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3961 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3962 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3963 EXPECT_EQ(new_page_scale
,
3964 grand_child
->draw_transform().matrix().getDouble(0, 0));
3965 EXPECT_EQ(new_page_scale
,
3966 grand_child
->draw_transform().matrix().getDouble(1, 1));
3969 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3970 SetupScrollAndContentsLayers(gfx::Size(30, 30));
3972 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3973 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3975 // Make the outer scroll layer scrollable.
3976 outer_scroll
->SetBounds(gfx::Size(50, 50));
3980 gfx::Vector2d
scroll_delta(0, 10);
3981 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3982 gfx::ScrollOffset
expected_max_scroll(outer_scroll
->MaxScrollOffset());
3983 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3984 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3985 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3986 host_impl_
->ScrollEnd();
3988 float page_scale
= 2.f
;
3989 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3994 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3995 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3996 expected_scroll_delta
));
3998 // The scroll range should not have changed.
3999 EXPECT_EQ(outer_scroll
->MaxScrollOffset(), expected_max_scroll
);
4001 // The page scale delta remains constant because the impl thread did not
4003 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
4006 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
4007 // Scroll a child layer beyond its maximum scroll range and make sure the
4008 // parent layer is scrolled on the axis on which the child was unable to
4010 gfx::Size
surface_size(10, 10);
4011 gfx::Size
content_size(20, 20);
4012 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4013 root
->SetBounds(surface_size
);
4014 root
->SetHasRenderSurface(true);
4015 scoped_ptr
<LayerImpl
> grand_child
=
4016 CreateScrollableLayer(3, content_size
, root
.get());
4018 scoped_ptr
<LayerImpl
> child
=
4019 CreateScrollableLayer(2, content_size
, root
.get());
4020 LayerImpl
* grand_child_layer
= grand_child
.get();
4021 child
->AddChild(grand_child
.Pass());
4023 LayerImpl
* child_layer
= child
.get();
4024 root
->AddChild(child
.Pass());
4025 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4026 host_impl_
->active_tree()->DidBecomeActive();
4027 host_impl_
->SetViewportSize(surface_size
);
4028 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
4029 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
4033 gfx::Vector2d
scroll_delta(-8, -7);
4034 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4035 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4036 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4037 host_impl_
->ScrollEnd();
4039 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4040 host_impl_
->ProcessScrollDeltas();
4042 // The grand child should have scrolled up to its limit.
4043 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
4044 LayerImpl
* grand_child
= child
->children()[0];
4045 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4046 gfx::Vector2d(0, -5)));
4048 // The child should have only scrolled on the other axis.
4049 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4050 gfx::Vector2d(-3, 0)));
4054 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
4055 // Scroll a child layer beyond its maximum scroll range and make sure the
4056 // the scroll doesn't bubble up to the parent layer.
4057 gfx::Size
surface_size(20, 20);
4058 gfx::Size
viewport_size(10, 10);
4059 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4060 root
->SetHasRenderSurface(true);
4061 scoped_ptr
<LayerImpl
> root_scrolling
=
4062 CreateScrollableLayer(2, surface_size
, root
.get());
4063 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
4065 scoped_ptr
<LayerImpl
> grand_child
=
4066 CreateScrollableLayer(4, surface_size
, root
.get());
4068 scoped_ptr
<LayerImpl
> child
=
4069 CreateScrollableLayer(3, surface_size
, root
.get());
4070 LayerImpl
* grand_child_layer
= grand_child
.get();
4071 child
->AddChild(grand_child
.Pass());
4073 LayerImpl
* child_layer
= child
.get();
4074 root_scrolling
->AddChild(child
.Pass());
4075 root
->AddChild(root_scrolling
.Pass());
4076 EXPECT_EQ(viewport_size
, root
->bounds());
4077 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4078 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4080 host_impl_
->active_tree()->DidBecomeActive();
4081 host_impl_
->SetViewportSize(viewport_size
);
4083 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4084 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4088 gfx::Vector2d
scroll_delta(0, -10);
4089 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4090 host_impl_
->ScrollBegin(gfx::Point(),
4091 InputHandler::NON_BUBBLING_GESTURE
));
4092 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4093 host_impl_
->ScrollEnd();
4095 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4096 host_impl_
->ProcessScrollDeltas();
4098 // The grand child should have scrolled up to its limit.
4100 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
4101 LayerImpl
* grand_child
= child
->children()[0];
4102 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4103 gfx::Vector2d(0, -2)));
4105 // The child should not have scrolled.
4106 ExpectNone(*scroll_info
.get(), child
->id());
4108 // The next time we scroll we should only scroll the parent.
4109 scroll_delta
= gfx::Vector2d(0, -3);
4110 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4111 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4112 InputHandler::NON_BUBBLING_GESTURE
));
4113 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4114 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4115 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
4116 host_impl_
->ScrollEnd();
4118 scroll_info
= host_impl_
->ProcessScrollDeltas();
4120 // The child should have scrolled up to its limit.
4121 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4122 gfx::Vector2d(0, -3)));
4124 // The grand child should not have scrolled.
4125 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4126 gfx::Vector2d(0, -2)));
4128 // After scrolling the parent, another scroll on the opposite direction
4129 // should still scroll the child.
4130 scroll_delta
= gfx::Vector2d(0, 7);
4131 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4132 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4133 InputHandler::NON_BUBBLING_GESTURE
));
4134 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4135 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4136 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4137 host_impl_
->ScrollEnd();
4139 scroll_info
= host_impl_
->ProcessScrollDeltas();
4141 // The grand child should have scrolled.
4142 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4143 gfx::Vector2d(0, 5)));
4145 // The child should not have scrolled.
4146 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4147 gfx::Vector2d(0, -3)));
4149 // Scrolling should be adjusted from viewport space.
4150 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
4151 host_impl_
->active_tree()->SetPageScaleOnActiveTree(2.f
);
4153 scroll_delta
= gfx::Vector2d(0, -2);
4154 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4155 host_impl_
->ScrollBegin(gfx::Point(1, 1),
4156 InputHandler::NON_BUBBLING_GESTURE
));
4157 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
4158 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4159 host_impl_
->ScrollEnd();
4161 scroll_info
= host_impl_
->ProcessScrollDeltas();
4163 // Should have scrolled by half the amount in layer space (5 - 2/2)
4164 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4165 gfx::Vector2d(0, 4)));
4168 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
4169 // When we try to scroll a non-scrollable child layer, the scroll delta
4170 // should be applied to one of its ancestors if possible.
4171 gfx::Size
surface_size(10, 10);
4172 gfx::Size
content_size(20, 20);
4173 scoped_ptr
<LayerImpl
> root_clip
=
4174 LayerImpl::Create(host_impl_
->active_tree(), 3);
4175 root_clip
->SetHasRenderSurface(true);
4176 scoped_ptr
<LayerImpl
> root
=
4177 CreateScrollableLayer(1, content_size
, root_clip
.get());
4178 // Make 'root' the clip layer for child: since they have the same sizes the
4179 // child will have zero max_scroll_offset and scrolls will bubble.
4180 scoped_ptr
<LayerImpl
> child
=
4181 CreateScrollableLayer(2, content_size
, root
.get());
4182 child
->SetIsContainerForFixedPositionLayers(true);
4183 root
->SetBounds(content_size
);
4185 int root_scroll_id
= root
->id();
4186 root
->AddChild(child
.Pass());
4187 root_clip
->AddChild(root
.Pass());
4189 host_impl_
->SetViewportSize(surface_size
);
4190 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4191 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
4193 host_impl_
->active_tree()->DidBecomeActive();
4196 gfx::Vector2d
scroll_delta(0, 4);
4197 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4198 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4199 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4200 host_impl_
->ScrollEnd();
4202 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4203 host_impl_
->ProcessScrollDeltas();
4205 // Only the root scroll should have scrolled.
4206 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
4208 ScrollInfoContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
));
4212 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
4213 gfx::Size
surface_size(10, 10);
4214 scoped_ptr
<LayerImpl
> root_clip
=
4215 LayerImpl::Create(host_impl_
->active_tree(), 1);
4216 scoped_ptr
<LayerImpl
> root_scroll
=
4217 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4218 root_scroll
->SetIsContainerForFixedPositionLayers(true);
4219 root_clip
->SetHasRenderSurface(true);
4220 root_clip
->AddChild(root_scroll
.Pass());
4221 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4222 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4224 host_impl_
->active_tree()->DidBecomeActive();
4225 host_impl_
->SetViewportSize(surface_size
);
4227 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4230 host_impl_
->active_tree()->DetachLayerTree();
4231 scoped_ptr
<LayerImpl
> root_clip2
=
4232 LayerImpl::Create(host_impl_
->active_tree(), 3);
4233 scoped_ptr
<LayerImpl
> root_scroll2
=
4234 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
4235 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
4236 root_clip2
->AddChild(root_scroll2
.Pass());
4237 root_clip2
->SetHasRenderSurface(true);
4238 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
4239 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
4241 host_impl_
->active_tree()->DidBecomeActive();
4243 // Scrolling should still work even though we did not draw yet.
4244 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4245 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4248 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
4249 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4251 // Rotate the root layer 90 degrees counter-clockwise about its center.
4252 gfx::Transform rotate_transform
;
4253 rotate_transform
.Rotate(-90.0);
4254 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
4256 gfx::Size
surface_size(50, 50);
4257 host_impl_
->SetViewportSize(surface_size
);
4260 // Scroll to the right in screen coordinates with a gesture.
4261 gfx::Vector2d
gesture_scroll_delta(10, 0);
4262 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4263 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4264 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4265 host_impl_
->ScrollEnd();
4267 // The layer should have scrolled down in its local coordinates.
4268 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4269 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4270 gfx::Vector2d(0, gesture_scroll_delta
.x())));
4272 // Reset and scroll down with the wheel.
4273 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4274 gfx::Vector2d
wheel_scroll_delta(0, 10);
4275 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4276 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4277 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4278 host_impl_
->ScrollEnd();
4280 // The layer should have scrolled down in its local coordinates.
4281 scroll_info
= host_impl_
->ProcessScrollDeltas();
4282 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4283 wheel_scroll_delta
));
4286 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
4287 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4288 int child_clip_layer_id
= 6;
4289 int child_layer_id
= 7;
4290 float child_layer_angle
= -20.f
;
4292 // Create a child layer that is rotated to a non-axis-aligned angle.
4293 scoped_ptr
<LayerImpl
> clip_layer
=
4294 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4295 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4296 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4297 gfx::Transform rotate_transform
;
4298 rotate_transform
.Translate(-50.0, -50.0);
4299 rotate_transform
.Rotate(child_layer_angle
);
4300 rotate_transform
.Translate(50.0, 50.0);
4301 clip_layer
->SetTransform(rotate_transform
);
4303 // Only allow vertical scrolling.
4304 clip_layer
->SetBounds(
4305 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
4306 // The rotation depends on the layer's transform origin, and the child layer
4307 // is a different size than the clip, so make sure the clip layer's origin
4308 // lines up over the child.
4309 clip_layer
->SetTransformOrigin(gfx::Point3F(
4310 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
4311 LayerImpl
* child_ptr
= child
.get();
4312 clip_layer
->AddChild(child
.Pass());
4313 scroll_layer
->AddChild(clip_layer
.Pass());
4315 gfx::Size
surface_size(50, 50);
4316 host_impl_
->SetViewportSize(surface_size
);
4319 // Scroll down in screen coordinates with a gesture.
4320 gfx::Vector2d
gesture_scroll_delta(0, 10);
4321 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4322 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4323 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4324 host_impl_
->ScrollEnd();
4326 // The child layer should have scrolled down in its local coordinates an
4327 // amount proportional to the angle between it and the input scroll delta.
4328 gfx::Vector2d
expected_scroll_delta(
4329 0, gesture_scroll_delta
.y() *
4330 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
4331 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4332 host_impl_
->ProcessScrollDeltas();
4333 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4334 expected_scroll_delta
));
4336 // The root scroll layer should not have scrolled, because the input delta
4337 // was close to the layer's axis of movement.
4338 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4341 // Now reset and scroll the same amount horizontally.
4342 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4343 gfx::Vector2d
gesture_scroll_delta(10, 0);
4344 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4345 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4346 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4347 host_impl_
->ScrollEnd();
4349 // The child layer should have scrolled down in its local coordinates an
4350 // amount proportional to the angle between it and the input scroll delta.
4351 gfx::Vector2d
expected_scroll_delta(
4352 0, -gesture_scroll_delta
.x() *
4353 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
4354 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4355 host_impl_
->ProcessScrollDeltas();
4356 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4357 expected_scroll_delta
));
4359 // The root scroll layer should have scrolled more, since the input scroll
4360 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4361 gfx::Vector2d
expected_root_scroll_delta(
4362 gesture_scroll_delta
.x() *
4363 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
4365 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4366 expected_root_scroll_delta
));
4370 TEST_F(LayerTreeHostImplTest
, ScrollPerspectiveTransformedLayer
) {
4371 // When scrolling an element with perspective, the distance scrolled
4372 // depends on the point at which the scroll begins.
4373 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4374 int child_clip_layer_id
= 6;
4375 int child_layer_id
= 7;
4377 // Create a child layer that is rotated on its x axis, with perspective.
4378 scoped_ptr
<LayerImpl
> clip_layer
=
4379 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4380 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4381 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4382 LayerImpl
* child_ptr
= child
.get();
4383 gfx::Transform perspective_transform
;
4384 perspective_transform
.Translate(-50.0, -50.0);
4385 perspective_transform
.ApplyPerspectiveDepth(20);
4386 perspective_transform
.RotateAboutXAxis(45);
4387 perspective_transform
.Translate(50.0, 50.0);
4388 clip_layer
->SetTransform(perspective_transform
);
4390 clip_layer
->SetBounds(gfx::Size(child_ptr
->bounds().width() / 2,
4391 child_ptr
->bounds().height() / 2));
4392 // The transform depends on the layer's transform origin, and the child layer
4393 // is a different size than the clip, so make sure the clip layer's origin
4394 // lines up over the child.
4395 clip_layer
->SetTransformOrigin(gfx::Point3F(
4396 clip_layer
->bounds().width(), clip_layer
->bounds().height(), 0.f
));
4397 clip_layer
->AddChild(child
.Pass());
4398 scroll_layer
->AddChild(clip_layer
.Pass());
4400 gfx::Size
surface_size(50, 50);
4401 host_impl_
->SetViewportSize(surface_size
);
4403 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
4405 gfx::Vector2d gesture_scroll_deltas
[4];
4406 gesture_scroll_deltas
[0] = gfx::Vector2d(4, 10);
4407 gesture_scroll_deltas
[1] = gfx::Vector2d(4, 10);
4408 gesture_scroll_deltas
[2] = gfx::Vector2d(10, 0);
4409 gesture_scroll_deltas
[3] = gfx::Vector2d(10, 0);
4411 gfx::Vector2d expected_scroll_deltas
[4];
4412 // Perspective affects the vertical delta by a different
4413 // amount depending on the vertical position of the |viewport_point|.
4414 expected_scroll_deltas
[0] = gfx::Vector2d(2, 8);
4415 expected_scroll_deltas
[1] = gfx::Vector2d(1, 4);
4416 // Deltas which start with the same vertical position of the
4417 // |viewport_point| are subject to identical perspective effects.
4418 expected_scroll_deltas
[2] = gfx::Vector2d(4, 0);
4419 expected_scroll_deltas
[3] = gfx::Vector2d(4, 0);
4421 gfx::Point
viewport_point(1, 1);
4423 // Scroll in screen coordinates with a gesture. Each scroll starts
4424 // where the previous scroll ended, but the scroll position is reset
4426 for (int i
= 0; i
< 4; ++i
) {
4427 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4429 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4430 host_impl_
->ScrollBegin(viewport_point
, InputHandler::GESTURE
));
4431 host_impl_
->ScrollBy(viewport_point
, gesture_scroll_deltas
[i
]);
4432 viewport_point
+= gesture_scroll_deltas
[i
];
4433 host_impl_
->ScrollEnd();
4435 scroll_info
= host_impl_
->ProcessScrollDeltas();
4436 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4437 expected_scroll_deltas
[i
]));
4439 // The root scroll layer should not have scrolled, because the input delta
4440 // was close to the layer's axis of movement.
4441 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4445 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
4446 LayerImpl
* scroll_layer
=
4447 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4449 // Scale the layer to twice its normal size.
4451 gfx::Transform scale_transform
;
4452 scale_transform
.Scale(scale
, scale
);
4453 scroll_layer
->SetTransform(scale_transform
);
4455 gfx::Size
surface_size(50, 50);
4456 host_impl_
->SetViewportSize(surface_size
);
4459 // Scroll down in screen coordinates with a gesture.
4460 gfx::Vector2d
scroll_delta(0, 10);
4461 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4462 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4463 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4464 host_impl_
->ScrollEnd();
4466 // The layer should have scrolled down in its local coordinates, but half the
4468 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4469 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4470 gfx::Vector2d(0, scroll_delta
.y() / scale
)));
4472 // Reset and scroll down with the wheel.
4473 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4474 gfx::Vector2d
wheel_scroll_delta(0, 10);
4475 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4476 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4477 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4478 host_impl_
->ScrollEnd();
4480 // It should apply the scale factor to the scroll delta for the wheel event.
4481 scroll_info
= host_impl_
->ProcessScrollDeltas();
4482 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4483 wheel_scroll_delta
));
4486 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
4490 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
4491 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
4492 gfx::Size(width
* scale
- 1, height
* scale
));
4493 host_impl_
->SetDeviceScaleFactor(scale
);
4494 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4496 LayerImpl
* inner_viewport_scroll_layer
=
4497 host_impl_
->active_tree()->InnerViewportScrollLayer();
4498 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4499 inner_viewport_scroll_layer
->MaxScrollOffset());
4502 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
4504 TestScrollOffsetDelegate()
4505 : page_scale_factor_(0.f
),
4506 min_page_scale_factor_(-1.f
),
4507 max_page_scale_factor_(-1.f
) {}
4509 ~TestScrollOffsetDelegate() override
{}
4511 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
4512 const gfx::ScrollOffset
& max_scroll_offset
,
4513 const gfx::SizeF
& scrollable_size
,
4514 float page_scale_factor
,
4515 float min_page_scale_factor
,
4516 float max_page_scale_factor
) override
{
4517 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
4518 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
4519 last_set_scroll_offset_
= total_scroll_offset
;
4520 max_scroll_offset_
= max_scroll_offset
;
4521 scrollable_size_
= scrollable_size
;
4522 page_scale_factor_
= page_scale_factor
;
4523 min_page_scale_factor_
= min_page_scale_factor
;
4524 max_page_scale_factor_
= max_page_scale_factor
;
4527 gfx::ScrollOffset
last_set_scroll_offset() {
4528 return last_set_scroll_offset_
;
4531 gfx::ScrollOffset
max_scroll_offset() const {
4532 return max_scroll_offset_
;
4535 gfx::SizeF
scrollable_size() const {
4536 return scrollable_size_
;
4539 float page_scale_factor() const {
4540 return page_scale_factor_
;
4543 float min_page_scale_factor() const {
4544 return min_page_scale_factor_
;
4547 float max_page_scale_factor() const {
4548 return max_page_scale_factor_
;
4552 gfx::ScrollOffset last_set_scroll_offset_
;
4553 gfx::ScrollOffset max_scroll_offset_
;
4554 gfx::SizeF scrollable_size_
;
4555 float page_scale_factor_
;
4556 float min_page_scale_factor_
;
4557 float max_page_scale_factor_
;
4560 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4561 TestScrollOffsetDelegate scroll_delegate
;
4562 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4563 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4564 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4565 clip_layer
->SetBounds(gfx::Size(10, 20));
4567 // Setting the delegate results in the current scroll offset being set.
4568 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4569 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4570 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4571 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4572 EXPECT_EQ(initial_scroll_delta
.ToString(),
4573 scroll_delegate
.last_set_scroll_offset().ToString());
4575 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4576 // page_scale_factor and {min|max}_page_scale_factor being set.
4577 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4578 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4579 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4580 EXPECT_EQ(1.f
, scroll_delegate
.min_page_scale_factor());
4581 EXPECT_EQ(1.f
, scroll_delegate
.max_page_scale_factor());
4583 // Updating page scale immediately updates the delegate.
4584 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4585 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4586 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4587 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4588 host_impl_
->active_tree()->SetPageScaleOnActiveTree(2.f
* 1.5f
);
4589 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
4590 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4591 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4592 host_impl_
->active_tree()->SetPageScaleOnActiveTree(2.f
);
4593 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4594 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4595 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4596 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4598 // The pinch gesture doesn't put the delegate into a state where the scroll
4599 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4601 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4602 host_impl_
->PinchGestureBegin();
4603 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4604 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4605 host_impl_
->PinchGestureEnd();
4606 host_impl_
->ScrollEnd();
4608 // Scrolling should be relative to the offset as given by the delegate.
4609 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4610 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4612 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4613 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4614 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4616 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4617 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4618 scroll_delegate
.last_set_scroll_offset());
4620 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4621 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4622 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4623 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4624 scroll_delegate
.last_set_scroll_offset());
4625 host_impl_
->ScrollEnd();
4626 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(gfx::ScrollOffset());
4628 // Forces a full tree synchronization and ensures that the scroll delegate
4629 // sees the correct size of the new tree.
4630 gfx::Size
new_size(42, 24);
4631 host_impl_
->CreatePendingTree();
4632 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
4633 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4634 host_impl_
->ActivateSyncTree();
4635 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4637 // Un-setting the delegate should propagate the delegate's current offset to
4638 // the root scrollable layer.
4639 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4640 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4641 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4643 EXPECT_EQ(current_offset
.ToString(),
4644 scroll_layer
->CurrentScrollOffset().ToString());
4647 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4648 const gfx::Transform target_space_transform
=
4649 layer
->draw_properties().target_space_transform
;
4650 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4651 gfx::Point translated_point
;
4652 target_space_transform
.TransformPoint(&translated_point
);
4653 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4654 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4657 TEST_F(LayerTreeHostImplTest
,
4658 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4659 TestScrollOffsetDelegate scroll_delegate
;
4660 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4661 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4662 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4663 clip_layer
->SetBounds(gfx::Size(10, 20));
4664 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4666 // Draw first frame to clear any pending draws and check scroll.
4668 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4669 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4671 // Set external scroll delta on delegate and notify LayerTreeHost.
4672 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4673 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(scroll_offset
);
4675 // Check scroll delta reflected in layer.
4676 LayerTreeHostImpl::FrameData frame
;
4677 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4678 host_impl_
->DrawLayers(&frame
);
4679 host_impl_
->DidDrawAllLayers(frame
);
4680 EXPECT_FALSE(frame
.has_no_damage
);
4681 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4683 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4686 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4687 InputHandlerScrollResult scroll_result
;
4688 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4689 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4690 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4692 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4694 // In-bounds scrolling does not affect overscroll.
4695 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4696 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4697 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4698 EXPECT_TRUE(scroll_result
.did_scroll
);
4699 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4700 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4701 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4703 // Overscroll events are reflected immediately.
4704 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4705 EXPECT_TRUE(scroll_result
.did_scroll
);
4706 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4707 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4708 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4709 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4710 host_impl_
->accumulated_root_overscroll());
4712 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4713 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4714 EXPECT_TRUE(scroll_result
.did_scroll
);
4715 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4716 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4717 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4718 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4719 host_impl_
->accumulated_root_overscroll());
4721 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4722 EXPECT_FALSE(scroll_result
.did_scroll
);
4723 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4724 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4725 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4726 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4727 host_impl_
->accumulated_root_overscroll());
4729 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4730 EXPECT_TRUE(scroll_result
.did_scroll
);
4731 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4732 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4733 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4734 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4735 host_impl_
->accumulated_root_overscroll());
4737 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4738 EXPECT_TRUE(scroll_result
.did_scroll
);
4739 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4740 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4741 EXPECT_EQ(gfx::Vector2dF(-5, -10), 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, 60));
4746 EXPECT_TRUE(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(-5, 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, -60));
4754 EXPECT_TRUE(scroll_result
.did_scroll
);
4755 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4756 EXPECT_EQ(gfx::Vector2dF(0, -10), 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 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4762 // as no scroll occurs.
4763 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4764 EXPECT_FALSE(scroll_result
.did_scroll
);
4765 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4766 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4767 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4768 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4769 host_impl_
->accumulated_root_overscroll());
4771 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4772 EXPECT_FALSE(scroll_result
.did_scroll
);
4773 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4774 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4775 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4776 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4777 host_impl_
->accumulated_root_overscroll());
4779 // Overscroll resets on valid scroll.
4780 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4781 EXPECT_TRUE(scroll_result
.did_scroll
);
4782 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4783 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4784 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4785 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4786 host_impl_
->accumulated_root_overscroll());
4788 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4789 EXPECT_TRUE(scroll_result
.did_scroll
);
4790 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4791 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4792 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4793 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4794 host_impl_
->accumulated_root_overscroll());
4796 host_impl_
->ScrollEnd();
4800 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4801 // Scroll child layers beyond their maximum scroll range and make sure root
4802 // overscroll does not accumulate.
4803 InputHandlerScrollResult scroll_result
;
4804 gfx::Size
surface_size(10, 10);
4805 scoped_ptr
<LayerImpl
> root_clip
=
4806 LayerImpl::Create(host_impl_
->active_tree(), 4);
4807 root_clip
->SetHasRenderSurface(true);
4809 scoped_ptr
<LayerImpl
> root
=
4810 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4812 scoped_ptr
<LayerImpl
> grand_child
=
4813 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4815 scoped_ptr
<LayerImpl
> child
=
4816 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4817 LayerImpl
* grand_child_layer
= grand_child
.get();
4818 child
->AddChild(grand_child
.Pass());
4820 LayerImpl
* child_layer
= child
.get();
4821 root
->AddChild(child
.Pass());
4822 root_clip
->AddChild(root
.Pass());
4823 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4824 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4825 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4826 host_impl_
->active_tree()->DidBecomeActive();
4827 host_impl_
->SetViewportSize(surface_size
);
4830 gfx::Vector2d
scroll_delta(0, -10);
4831 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4832 host_impl_
->ScrollBegin(gfx::Point(),
4833 InputHandler::NON_BUBBLING_GESTURE
));
4834 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4835 EXPECT_TRUE(scroll_result
.did_scroll
);
4836 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4837 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4838 host_impl_
->ScrollEnd();
4840 // The next time we scroll we should only scroll the parent, but overscroll
4841 // should still not reach the root layer.
4842 scroll_delta
= gfx::Vector2d(0, -30);
4843 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4844 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4845 InputHandler::NON_BUBBLING_GESTURE
));
4846 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4847 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4848 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4849 EXPECT_TRUE(scroll_result
.did_scroll
);
4850 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4851 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4852 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4853 host_impl_
->ScrollEnd();
4855 // After scrolling the parent, another scroll on the opposite direction
4856 // should scroll the child.
4857 scroll_delta
= gfx::Vector2d(0, 70);
4858 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4859 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4860 InputHandler::NON_BUBBLING_GESTURE
));
4861 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4862 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4863 EXPECT_TRUE(scroll_result
.did_scroll
);
4864 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4865 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4866 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4867 host_impl_
->ScrollEnd();
4871 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4872 // When we try to scroll a non-scrollable child layer, the scroll delta
4873 // should be applied to one of its ancestors if possible. Overscroll should
4874 // be reflected only when it has bubbled up to the root scrolling layer.
4875 InputHandlerScrollResult scroll_result
;
4876 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4879 gfx::Vector2d
scroll_delta(0, 8);
4880 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4881 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4882 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4883 EXPECT_TRUE(scroll_result
.did_scroll
);
4884 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4885 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4886 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4887 EXPECT_TRUE(scroll_result
.did_scroll
);
4888 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4889 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4890 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4891 EXPECT_FALSE(scroll_result
.did_scroll
);
4892 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4893 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4894 host_impl_
->ScrollEnd();
4898 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4899 InputHandlerScrollResult scroll_result
;
4900 LayerTreeSettings settings
;
4901 CreateHostImpl(settings
, CreateOutputSurface());
4903 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4904 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4905 clip_layer
->SetBounds(gfx::Size(50, 50));
4906 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4907 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4909 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4911 // Even though the layer can't scroll the overscroll still happens.
4912 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4913 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4914 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4915 EXPECT_FALSE(scroll_result
.did_scroll
);
4916 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4917 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4920 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4921 InputHandlerScrollResult scroll_result
;
4922 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4926 // Edge glow effect should be applicable only upon reaching Edges
4927 // of the content. unnecessary glow effect calls shouldn't be
4928 // called while scrolling up without reaching the edge of the content.
4929 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4930 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4931 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4932 EXPECT_TRUE(scroll_result
.did_scroll
);
4933 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4934 EXPECT_EQ(gfx::Vector2dF().ToString(),
4935 host_impl_
->accumulated_root_overscroll().ToString());
4937 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4938 EXPECT_TRUE(scroll_result
.did_scroll
);
4939 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4940 EXPECT_EQ(gfx::Vector2dF().ToString(),
4941 host_impl_
->accumulated_root_overscroll().ToString());
4942 host_impl_
->ScrollEnd();
4943 // unusedrootDelta should be subtracted from applied delta so that
4944 // unwanted glow effect calls are not called.
4945 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4946 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4947 InputHandler::NON_BUBBLING_GESTURE
));
4948 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4949 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4950 EXPECT_TRUE(scroll_result
.did_scroll
);
4951 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4952 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4953 host_impl_
->accumulated_root_overscroll().ToString());
4956 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4957 EXPECT_FALSE(scroll_result
.did_scroll
);
4958 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4959 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4960 host_impl_
->accumulated_root_overscroll().ToString());
4961 host_impl_
->ScrollEnd();
4962 // TestCase to check kEpsilon, which prevents minute values to trigger
4963 // gloweffect without reaching edge.
4964 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4965 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4967 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4968 EXPECT_FALSE(scroll_result
.did_scroll
);
4969 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4970 EXPECT_EQ(gfx::Vector2dF().ToString(),
4971 host_impl_
->accumulated_root_overscroll().ToString());
4972 host_impl_
->ScrollEnd();
4976 class BlendStateCheckLayer
: public LayerImpl
{
4978 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4980 ResourceProvider
* resource_provider
) {
4981 return make_scoped_ptr(
4982 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4985 void AppendQuads(RenderPass
* render_pass
,
4986 AppendQuadsData
* append_quads_data
) override
{
4987 quads_appended_
= true;
4989 gfx::Rect opaque_rect
;
4990 if (contents_opaque())
4991 opaque_rect
= quad_rect_
;
4993 opaque_rect
= opaque_content_rect_
;
4994 gfx::Rect visible_quad_rect
= quad_rect_
;
4996 SharedQuadState
* shared_quad_state
=
4997 render_pass
->CreateAndAppendSharedQuadState();
4998 PopulateSharedQuadState(shared_quad_state
);
5000 TileDrawQuad
* test_blending_draw_quad
=
5001 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
5002 test_blending_draw_quad
->SetNew(shared_quad_state
,
5007 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
5011 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
5012 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
5013 EXPECT_EQ(has_render_surface_
, !!render_surface());
5016 void SetExpectation(bool blend
, bool has_render_surface
) {
5018 has_render_surface_
= has_render_surface
;
5019 quads_appended_
= false;
5022 bool quads_appended() const { return quads_appended_
; }
5024 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
5025 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
5026 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
5027 opaque_content_rect_
= rect
;
5031 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
5033 ResourceProvider
* resource_provider
)
5034 : LayerImpl(tree_impl
, id
),
5036 has_render_surface_(false),
5037 quads_appended_(false),
5038 quad_rect_(5, 5, 5, 5),
5039 quad_visible_rect_(5, 5, 5, 5),
5040 resource_id_(resource_provider
->CreateResource(
5043 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
5045 resource_provider
->AllocateForTesting(resource_id_
);
5046 SetBounds(gfx::Size(10, 10));
5047 SetDrawsContent(true);
5051 bool has_render_surface_
;
5052 bool quads_appended_
;
5053 gfx::Rect quad_rect_
;
5054 gfx::Rect opaque_content_rect_
;
5055 gfx::Rect quad_visible_rect_
;
5056 ResourceId resource_id_
;
5059 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
5061 scoped_ptr
<LayerImpl
> root
=
5062 LayerImpl::Create(host_impl_
->active_tree(), 1);
5063 root
->SetBounds(gfx::Size(10, 10));
5064 root
->SetDrawsContent(false);
5065 root
->SetHasRenderSurface(true);
5066 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5068 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5071 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5073 host_impl_
->resource_provider()));
5074 BlendStateCheckLayer
* layer1
=
5075 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
5076 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
5078 LayerTreeHostImpl::FrameData frame
;
5080 // Opaque layer, drawn without blending.
5081 layer1
->SetContentsOpaque(true);
5082 layer1
->SetExpectation(false, false);
5083 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5084 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5085 host_impl_
->DrawLayers(&frame
);
5086 EXPECT_TRUE(layer1
->quads_appended());
5087 host_impl_
->DidDrawAllLayers(frame
);
5089 // Layer with translucent content and painting, so drawn with blending.
5090 layer1
->SetContentsOpaque(false);
5091 layer1
->SetExpectation(true, false);
5092 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5093 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5094 host_impl_
->DrawLayers(&frame
);
5095 EXPECT_TRUE(layer1
->quads_appended());
5096 host_impl_
->DidDrawAllLayers(frame
);
5098 // Layer with translucent opacity, drawn with blending.
5099 layer1
->SetContentsOpaque(true);
5100 layer1
->SetOpacity(0.5f
);
5101 layer1
->SetExpectation(true, false);
5102 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5103 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5104 host_impl_
->DrawLayers(&frame
);
5105 EXPECT_TRUE(layer1
->quads_appended());
5106 host_impl_
->DidDrawAllLayers(frame
);
5108 // Layer with translucent opacity and painting, drawn with blending.
5109 layer1
->SetContentsOpaque(true);
5110 layer1
->SetOpacity(0.5f
);
5111 layer1
->SetExpectation(true, false);
5112 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5113 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5114 host_impl_
->DrawLayers(&frame
);
5115 EXPECT_TRUE(layer1
->quads_appended());
5116 host_impl_
->DidDrawAllLayers(frame
);
5119 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5121 host_impl_
->resource_provider()));
5122 BlendStateCheckLayer
* layer2
=
5123 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
5124 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
5126 // 2 opaque layers, drawn without blending.
5127 layer1
->SetContentsOpaque(true);
5128 layer1
->SetOpacity(1.f
);
5129 layer1
->SetExpectation(false, false);
5130 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5131 layer2
->SetContentsOpaque(true);
5132 layer2
->SetOpacity(1.f
);
5133 layer2
->SetExpectation(false, false);
5134 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5135 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5136 host_impl_
->DrawLayers(&frame
);
5137 EXPECT_TRUE(layer1
->quads_appended());
5138 EXPECT_TRUE(layer2
->quads_appended());
5139 host_impl_
->DidDrawAllLayers(frame
);
5141 // Parent layer with translucent content, drawn with blending.
5142 // Child layer with opaque content, drawn without blending.
5143 layer1
->SetContentsOpaque(false);
5144 layer1
->SetExpectation(true, false);
5145 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5146 layer2
->SetExpectation(false, false);
5147 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5148 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5149 host_impl_
->DrawLayers(&frame
);
5150 EXPECT_TRUE(layer1
->quads_appended());
5151 EXPECT_TRUE(layer2
->quads_appended());
5152 host_impl_
->DidDrawAllLayers(frame
);
5154 // Parent layer with translucent content but opaque painting, drawn without
5156 // Child layer with opaque content, drawn without blending.
5157 layer1
->SetContentsOpaque(true);
5158 layer1
->SetExpectation(false, false);
5159 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5160 layer2
->SetExpectation(false, false);
5161 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5162 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5163 host_impl_
->DrawLayers(&frame
);
5164 EXPECT_TRUE(layer1
->quads_appended());
5165 EXPECT_TRUE(layer2
->quads_appended());
5166 host_impl_
->DidDrawAllLayers(frame
);
5168 // Parent layer with translucent opacity and opaque content. Since it has a
5169 // drawing child, it's drawn to a render surface which carries the opacity,
5170 // so it's itself drawn without blending.
5171 // Child layer with opaque content, drawn without blending (parent surface
5172 // carries the inherited opacity).
5173 layer1
->SetContentsOpaque(true);
5174 layer1
->SetOpacity(0.5f
);
5175 layer1
->SetHasRenderSurface(true);
5176 layer1
->SetExpectation(false, true);
5177 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5178 layer2
->SetExpectation(false, false);
5179 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5180 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5181 host_impl_
->active_tree()->root_layer());
5182 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5183 host_impl_
->DrawLayers(&frame
);
5184 EXPECT_TRUE(layer1
->quads_appended());
5185 EXPECT_TRUE(layer2
->quads_appended());
5186 host_impl_
->DidDrawAllLayers(frame
);
5187 layer1
->SetHasRenderSurface(false);
5189 // Draw again, but with child non-opaque, to make sure
5190 // layer1 not culled.
5191 layer1
->SetContentsOpaque(true);
5192 layer1
->SetOpacity(1.f
);
5193 layer1
->SetExpectation(false, false);
5194 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5195 layer2
->SetContentsOpaque(true);
5196 layer2
->SetOpacity(0.5f
);
5197 layer2
->SetExpectation(true, false);
5198 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5199 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5200 host_impl_
->DrawLayers(&frame
);
5201 EXPECT_TRUE(layer1
->quads_appended());
5202 EXPECT_TRUE(layer2
->quads_appended());
5203 host_impl_
->DidDrawAllLayers(frame
);
5205 // A second way of making the child non-opaque.
5206 layer1
->SetContentsOpaque(true);
5207 layer1
->SetOpacity(1.f
);
5208 layer1
->SetExpectation(false, false);
5209 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5210 layer2
->SetContentsOpaque(false);
5211 layer2
->SetOpacity(1.f
);
5212 layer2
->SetExpectation(true, false);
5213 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5214 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5215 host_impl_
->DrawLayers(&frame
);
5216 EXPECT_TRUE(layer1
->quads_appended());
5217 EXPECT_TRUE(layer2
->quads_appended());
5218 host_impl_
->DidDrawAllLayers(frame
);
5220 // And when the layer says its not opaque but is painted opaque, it is not
5222 layer1
->SetContentsOpaque(true);
5223 layer1
->SetOpacity(1.f
);
5224 layer1
->SetExpectation(false, false);
5225 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5226 layer2
->SetContentsOpaque(true);
5227 layer2
->SetOpacity(1.f
);
5228 layer2
->SetExpectation(false, false);
5229 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5230 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5231 host_impl_
->DrawLayers(&frame
);
5232 EXPECT_TRUE(layer1
->quads_appended());
5233 EXPECT_TRUE(layer2
->quads_appended());
5234 host_impl_
->DidDrawAllLayers(frame
);
5236 // Layer with partially opaque contents, drawn with blending.
5237 layer1
->SetContentsOpaque(false);
5238 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5239 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5240 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5241 layer1
->SetExpectation(true, false);
5242 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5243 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5244 host_impl_
->DrawLayers(&frame
);
5245 EXPECT_TRUE(layer1
->quads_appended());
5246 host_impl_
->DidDrawAllLayers(frame
);
5248 // Layer with partially opaque contents partially culled, drawn with blending.
5249 layer1
->SetContentsOpaque(false);
5250 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5251 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5252 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5253 layer1
->SetExpectation(true, false);
5254 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5255 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5256 host_impl_
->DrawLayers(&frame
);
5257 EXPECT_TRUE(layer1
->quads_appended());
5258 host_impl_
->DidDrawAllLayers(frame
);
5260 // Layer with partially opaque contents culled, drawn with blending.
5261 layer1
->SetContentsOpaque(false);
5262 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5263 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 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 and translucent contents culled, drawn
5273 // without blending.
5274 layer1
->SetContentsOpaque(false);
5275 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5276 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5277 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5278 layer1
->SetExpectation(false, false);
5279 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5280 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5281 host_impl_
->DrawLayers(&frame
);
5282 EXPECT_TRUE(layer1
->quads_appended());
5283 host_impl_
->DidDrawAllLayers(frame
);
5286 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
5288 LayerTreeHostImplViewportCoveredTest() :
5289 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
5291 did_activate_pending_tree_(false) {}
5293 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
5295 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5297 return FakeOutputSurface::Create3d();
5300 void SetupActiveTreeLayers() {
5301 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
5302 host_impl_
->active_tree()->SetRootLayer(
5303 LayerImpl::Create(host_impl_
->active_tree(), 1));
5304 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
5305 host_impl_
->active_tree()->root_layer()->AddChild(
5306 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5308 host_impl_
->resource_provider()));
5309 child_
= static_cast<BlendStateCheckLayer
*>(
5310 host_impl_
->active_tree()->root_layer()->children()[0]);
5311 child_
->SetExpectation(false, false);
5312 child_
->SetContentsOpaque(true);
5315 // Expect no gutter rects.
5316 void TestLayerCoversFullViewport() {
5317 gfx::Rect
layer_rect(viewport_size_
);
5318 child_
->SetPosition(layer_rect
.origin());
5319 child_
->SetBounds(layer_rect
.size());
5320 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5321 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5323 LayerTreeHostImpl::FrameData frame
;
5324 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5325 ASSERT_EQ(1u, frame
.render_passes
.size());
5327 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5328 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5329 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5331 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5332 host_impl_
->DidDrawAllLayers(frame
);
5335 // Expect fullscreen gutter rect.
5336 void TestEmptyLayer() {
5337 gfx::Rect
layer_rect(0, 0, 0, 0);
5338 child_
->SetPosition(layer_rect
.origin());
5339 child_
->SetBounds(layer_rect
.size());
5340 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5341 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5343 LayerTreeHostImpl::FrameData frame
;
5344 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5345 ASSERT_EQ(1u, frame
.render_passes
.size());
5347 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5348 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5349 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5351 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5352 host_impl_
->DidDrawAllLayers(frame
);
5355 // Expect four surrounding gutter rects.
5356 void TestLayerInMiddleOfViewport() {
5357 gfx::Rect
layer_rect(500, 500, 200, 200);
5358 child_
->SetPosition(layer_rect
.origin());
5359 child_
->SetBounds(layer_rect
.size());
5360 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5361 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5363 LayerTreeHostImpl::FrameData frame
;
5364 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5365 ASSERT_EQ(1u, frame
.render_passes
.size());
5367 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5368 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
5369 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5371 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5372 host_impl_
->DidDrawAllLayers(frame
);
5375 // Expect no gutter rects.
5376 void TestLayerIsLargerThanViewport() {
5377 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
5378 viewport_size_
.height() + 10);
5379 child_
->SetPosition(layer_rect
.origin());
5380 child_
->SetBounds(layer_rect
.size());
5381 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5382 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5384 LayerTreeHostImpl::FrameData frame
;
5385 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5386 ASSERT_EQ(1u, frame
.render_passes
.size());
5388 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5389 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5390 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5392 host_impl_
->DidDrawAllLayers(frame
);
5395 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
5397 void set_gutter_quad_material(DrawQuad::Material material
) {
5398 gutter_quad_material_
= material
;
5400 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
5401 gutter_texture_size_
= gutter_texture_size
;
5405 size_t CountGutterQuads(const QuadList
& quad_list
) {
5406 size_t num_gutter_quads
= 0;
5407 for (const auto& quad
: quad_list
) {
5408 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
5410 return num_gutter_quads
;
5413 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
5414 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5415 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
5418 // Make sure that the texture coordinates match their expectations.
5419 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
5420 for (const auto& quad
: quad_list
) {
5421 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
5423 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
5424 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
5425 gutter_texture_size_
, host_impl_
->device_scale_factor());
5426 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
5427 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
5428 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
5429 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
5431 texture_quad
->uv_bottom_right
.x(),
5432 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
5434 texture_quad
->uv_bottom_right
.y(),
5435 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
5439 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
5440 return gfx::ToRoundedSize(
5441 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
5444 DrawQuad::Material gutter_quad_material_
;
5445 gfx::Size gutter_texture_size_
;
5446 gfx::Size viewport_size_
;
5447 BlendStateCheckLayer
* child_
;
5448 bool did_activate_pending_tree_
;
5451 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
5452 viewport_size_
= gfx::Size(1000, 1000);
5454 bool always_draw
= false;
5455 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5457 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5458 SetupActiveTreeLayers();
5459 TestLayerCoversFullViewport();
5461 TestLayerInMiddleOfViewport();
5462 TestLayerIsLargerThanViewport();
5465 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
5466 viewport_size_
= gfx::Size(1000, 1000);
5468 bool always_draw
= false;
5469 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5471 host_impl_
->SetDeviceScaleFactor(2.f
);
5472 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5473 SetupActiveTreeLayers();
5474 TestLayerCoversFullViewport();
5476 TestLayerInMiddleOfViewport();
5477 TestLayerIsLargerThanViewport();
5480 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
5481 viewport_size_
= gfx::Size(1000, 1000);
5483 bool always_draw
= true;
5484 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5486 // Pending tree to force active_tree size invalid. Not used otherwise.
5487 host_impl_
->CreatePendingTree();
5488 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5489 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5491 SetupActiveTreeLayers();
5493 TestLayerInMiddleOfViewport();
5494 TestLayerIsLargerThanViewport();
5497 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5498 viewport_size_
= gfx::Size(1000, 1000);
5500 bool always_draw
= true;
5501 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5503 // Set larger viewport and activate it to active tree.
5504 host_impl_
->CreatePendingTree();
5505 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5506 viewport_size_
.height() + 100);
5507 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5508 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5509 host_impl_
->ActivateSyncTree();
5510 EXPECT_TRUE(did_activate_pending_tree_
);
5511 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5513 // Shrink pending tree viewport without activating.
5514 host_impl_
->CreatePendingTree();
5515 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5516 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5518 SetupActiveTreeLayers();
5520 TestLayerInMiddleOfViewport();
5521 TestLayerIsLargerThanViewport();
5524 class FakeDrawableLayerImpl
: public LayerImpl
{
5526 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5527 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5530 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5531 : LayerImpl(tree_impl
, id
) {}
5534 // Only reshape when we know we are going to draw. Otherwise, the reshape
5535 // can leave the window at the wrong size if we never draw and the proper
5536 // viewport size is never set.
5537 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5538 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5539 scoped_ptr
<OutputSurface
> output_surface(
5540 FakeOutputSurface::Create3d(provider
));
5541 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5543 scoped_ptr
<LayerImpl
> root
=
5544 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5545 root
->SetBounds(gfx::Size(10, 10));
5546 root
->SetDrawsContent(true);
5547 root
->SetHasRenderSurface(true);
5548 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5549 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5550 provider
->TestContext3d()->clear_reshape_called();
5552 LayerTreeHostImpl::FrameData frame
;
5553 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5554 host_impl_
->SetDeviceScaleFactor(1.f
);
5555 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5556 host_impl_
->DrawLayers(&frame
);
5557 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5558 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5559 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5560 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5561 host_impl_
->DidDrawAllLayers(frame
);
5562 provider
->TestContext3d()->clear_reshape_called();
5564 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5565 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5566 host_impl_
->DrawLayers(&frame
);
5567 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5568 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5569 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5570 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5571 host_impl_
->DidDrawAllLayers(frame
);
5572 provider
->TestContext3d()->clear_reshape_called();
5574 host_impl_
->SetDeviceScaleFactor(2.f
);
5575 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5576 host_impl_
->DrawLayers(&frame
);
5577 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5578 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5579 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5580 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5581 host_impl_
->DidDrawAllLayers(frame
);
5582 provider
->TestContext3d()->clear_reshape_called();
5585 // Make sure damage tracking propagates all the way to the graphics context,
5586 // where it should request to swap only the sub-buffer that is damaged.
5587 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5588 scoped_refptr
<TestContextProvider
> context_provider(
5589 TestContextProvider::Create());
5590 context_provider
->BindToCurrentThread();
5591 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5593 scoped_ptr
<FakeOutputSurface
> output_surface(
5594 FakeOutputSurface::Create3d(context_provider
));
5595 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5597 // This test creates its own LayerTreeHostImpl, so
5598 // that we can force partial swap enabled.
5599 LayerTreeSettings settings
;
5600 settings
.renderer_settings
.partial_swap_enabled
= true;
5601 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5602 LayerTreeHostImpl::Create(
5603 settings
, this, &proxy_
, &stats_instrumentation_
,
5604 &shared_bitmap_manager_
, NULL
, &task_graph_runner_
, 0);
5605 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5606 layer_tree_host_impl
->WillBeginImplFrame(
5607 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5608 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5610 scoped_ptr
<LayerImpl
> root
=
5611 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5612 root
->SetHasRenderSurface(true);
5613 scoped_ptr
<LayerImpl
> child
=
5614 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5615 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5616 child
->SetBounds(gfx::Size(14, 15));
5617 child
->SetDrawsContent(true);
5618 root
->SetBounds(gfx::Size(500, 500));
5619 root
->SetDrawsContent(true);
5620 root
->AddChild(child
.Pass());
5621 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5623 LayerTreeHostImpl::FrameData frame
;
5625 // First frame, the entire screen should get swapped.
5626 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5627 layer_tree_host_impl
->DrawLayers(&frame
);
5628 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5629 layer_tree_host_impl
->SwapBuffers(frame
);
5630 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5631 EXPECT_EQ(expected_swap_rect
.ToString(),
5632 fake_output_surface
->last_swap_rect().ToString());
5634 // Second frame, only the damaged area should get swapped. Damage should be
5635 // the union of old and new child rects.
5636 // expected damage rect: gfx::Rect(26, 28);
5637 // expected swap rect: vertically flipped, with origin at bottom left corner.
5638 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5640 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5641 layer_tree_host_impl
->DrawLayers(&frame
);
5642 host_impl_
->DidDrawAllLayers(frame
);
5643 layer_tree_host_impl
->SwapBuffers(frame
);
5645 // Make sure that partial swap is constrained to the viewport dimensions
5646 // expected damage rect: gfx::Rect(500, 500);
5647 // expected swap rect: flipped damage rect, but also clamped to viewport
5648 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5649 EXPECT_EQ(expected_swap_rect
.ToString(),
5650 fake_output_surface
->last_swap_rect().ToString());
5652 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5653 // This will damage everything.
5654 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5656 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5657 layer_tree_host_impl
->DrawLayers(&frame
);
5658 host_impl_
->DidDrawAllLayers(frame
);
5659 layer_tree_host_impl
->SwapBuffers(frame
);
5661 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5662 EXPECT_EQ(expected_swap_rect
.ToString(),
5663 fake_output_surface
->last_swap_rect().ToString());
5666 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5667 scoped_ptr
<LayerImpl
> root
=
5668 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5669 scoped_ptr
<LayerImpl
> child
=
5670 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5671 child
->SetBounds(gfx::Size(10, 10));
5672 child
->SetDrawsContent(true);
5673 root
->SetBounds(gfx::Size(10, 10));
5674 root
->SetDrawsContent(true);
5675 root
->SetHasRenderSurface(true);
5676 root
->AddChild(child
.Pass());
5678 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5680 LayerTreeHostImpl::FrameData frame
;
5682 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5683 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5684 EXPECT_EQ(1u, frame
.render_passes
.size());
5685 host_impl_
->DidDrawAllLayers(frame
);
5688 class FakeLayerWithQuads
: public LayerImpl
{
5690 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5691 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5694 void AppendQuads(RenderPass
* render_pass
,
5695 AppendQuadsData
* append_quads_data
) override
{
5696 SharedQuadState
* shared_quad_state
=
5697 render_pass
->CreateAndAppendSharedQuadState();
5698 PopulateSharedQuadState(shared_quad_state
);
5700 SkColor gray
= SkColorSetRGB(100, 100, 100);
5701 gfx::Rect
quad_rect(bounds());
5702 gfx::Rect
visible_quad_rect(quad_rect
);
5703 SolidColorDrawQuad
* my_quad
=
5704 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5706 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5710 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5711 : LayerImpl(tree_impl
, id
) {}
5714 class MockContext
: public TestWebGraphicsContext3D
{
5716 MOCK_METHOD1(useProgram
, void(GLuint program
));
5717 MOCK_METHOD5(uniform4f
, void(GLint location
,
5722 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5724 GLboolean transpose
,
5725 const GLfloat
* value
));
5726 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5730 MOCK_METHOD1(enable
, void(GLenum cap
));
5731 MOCK_METHOD1(disable
, void(GLenum cap
));
5732 MOCK_METHOD4(scissor
, void(GLint x
,
5738 class MockContextHarness
{
5740 MockContext
* context_
;
5743 explicit MockContextHarness(MockContext
* context
)
5744 : context_(context
) {
5745 context_
->set_have_post_sub_buffer(true);
5747 // Catch "uninteresting" calls
5748 EXPECT_CALL(*context_
, useProgram(_
))
5751 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5754 // These are not asserted
5755 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5756 .WillRepeatedly(Return());
5758 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5759 .WillRepeatedly(Return());
5761 // Any un-sanctioned calls to enable() are OK
5762 EXPECT_CALL(*context_
, enable(_
))
5763 .WillRepeatedly(Return());
5765 // Any un-sanctioned calls to disable() are OK
5766 EXPECT_CALL(*context_
, disable(_
))
5767 .WillRepeatedly(Return());
5770 void MustDrawSolidQuad() {
5771 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5773 .RetiresOnSaturation();
5775 EXPECT_CALL(*context_
, useProgram(_
))
5777 .RetiresOnSaturation();
5780 void MustSetScissor(int x
, int y
, int width
, int height
) {
5781 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5782 .WillRepeatedly(Return());
5784 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5786 .WillRepeatedly(Return());
5789 void MustSetNoScissor() {
5790 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5791 .WillRepeatedly(Return());
5793 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5796 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5801 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5802 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5803 MockContext
* mock_context
= mock_context_owned
.get();
5804 MockContextHarness
harness(mock_context
);
5807 LayerTreeSettings settings
= DefaultSettings();
5808 settings
.renderer_settings
.partial_swap_enabled
= false;
5809 CreateHostImpl(settings
,
5810 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5811 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5813 // Without partial swap, and no clipping, no scissor is set.
5814 harness
.MustDrawSolidQuad();
5815 harness
.MustSetNoScissor();
5817 LayerTreeHostImpl::FrameData frame
;
5818 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5819 host_impl_
->DrawLayers(&frame
);
5820 host_impl_
->DidDrawAllLayers(frame
);
5822 Mock::VerifyAndClearExpectations(&mock_context
);
5824 // Without partial swap, but a layer does clip its subtree, one scissor is
5826 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5827 harness
.MustDrawSolidQuad();
5828 harness
.MustSetScissor(0, 0, 10, 10);
5830 LayerTreeHostImpl::FrameData frame
;
5831 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
5832 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5833 host_impl_
->DrawLayers(&frame
);
5834 host_impl_
->DidDrawAllLayers(frame
);
5836 Mock::VerifyAndClearExpectations(&mock_context
);
5839 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5840 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5841 MockContext
* mock_context
= context_owned
.get();
5842 MockContextHarness
harness(mock_context
);
5844 LayerTreeSettings settings
= DefaultSettings();
5845 settings
.renderer_settings
.partial_swap_enabled
= true;
5846 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5847 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5849 // The first frame is not a partially-swapped one. No scissor should be set.
5850 harness
.MustSetNoScissor();
5851 harness
.MustDrawSolidQuad();
5853 LayerTreeHostImpl::FrameData frame
;
5854 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5855 host_impl_
->DrawLayers(&frame
);
5856 host_impl_
->DidDrawAllLayers(frame
);
5858 Mock::VerifyAndClearExpectations(&mock_context
);
5860 // Damage a portion of the frame.
5861 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5862 gfx::Rect(0, 0, 2, 3));
5864 // The second frame will be partially-swapped (the y coordinates are flipped).
5865 harness
.MustSetScissor(0, 7, 2, 3);
5866 harness
.MustDrawSolidQuad();
5868 LayerTreeHostImpl::FrameData frame
;
5869 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5870 host_impl_
->DrawLayers(&frame
);
5871 host_impl_
->DidDrawAllLayers(frame
);
5873 Mock::VerifyAndClearExpectations(&mock_context
);
5876 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5878 LayerTreeHostImplClient
* client
,
5880 SharedBitmapManager
* manager
,
5881 TaskGraphRunner
* task_graph_runner
,
5882 RenderingStatsInstrumentation
* stats_instrumentation
) {
5883 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5884 scoped_ptr
<OutputSurface
> output_surface(
5885 FakeOutputSurface::Create3d(provider
));
5886 provider
->BindToCurrentThread();
5887 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5889 LayerTreeSettings settings
;
5890 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5891 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5892 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
,
5893 manager
, nullptr, task_graph_runner
, 0);
5894 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5895 my_host_impl
->WillBeginImplFrame(
5896 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5897 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5900 Layers are created as follows:
5902 +--------------------+
5906 | | +-------------------+
5908 | | +-------------------+
5913 +--------------------+
5915 Layers 1, 2 have render surfaces
5917 scoped_ptr
<LayerImpl
> root
=
5918 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5919 scoped_ptr
<LayerImpl
> child
=
5920 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5921 scoped_ptr
<LayerImpl
> grand_child
=
5922 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5924 gfx::Rect
root_rect(0, 0, 100, 100);
5925 gfx::Rect
child_rect(10, 10, 50, 50);
5926 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5928 root
->SetHasRenderSurface(true);
5929 root
->SetPosition(root_rect
.origin());
5930 root
->SetBounds(root_rect
.size());
5931 root
->draw_properties().visible_layer_rect
= root_rect
;
5932 root
->SetDrawsContent(false);
5933 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5935 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5936 child
->SetOpacity(0.5f
);
5937 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5938 child
->draw_properties().visible_layer_rect
= child_rect
;
5939 child
->SetDrawsContent(false);
5940 child
->SetHasRenderSurface(true);
5942 grand_child
->SetPosition(grand_child_rect
.origin());
5943 grand_child
->SetBounds(grand_child_rect
.size());
5944 grand_child
->draw_properties().visible_layer_rect
= grand_child_rect
;
5945 grand_child
->SetDrawsContent(true);
5947 child
->AddChild(grand_child
.Pass());
5948 root
->AddChild(child
.Pass());
5950 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5951 return my_host_impl
.Pass();
5954 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5955 TestSharedBitmapManager shared_bitmap_manager
;
5956 TestTaskGraphRunner task_graph_runner
;
5957 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5958 SetupLayersForOpacity(true, this, &proxy_
, &shared_bitmap_manager
,
5959 &task_graph_runner
, &stats_instrumentation_
);
5961 LayerTreeHostImpl::FrameData frame
;
5962 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5964 // Verify all quads have been computed
5965 ASSERT_EQ(2U, frame
.render_passes
.size());
5966 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5967 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5968 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5969 frame
.render_passes
[0]->quad_list
.front()->material
);
5970 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5971 frame
.render_passes
[1]->quad_list
.front()->material
);
5973 my_host_impl
->DrawLayers(&frame
);
5974 my_host_impl
->DidDrawAllLayers(frame
);
5978 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5979 TestSharedBitmapManager shared_bitmap_manager
;
5980 TestTaskGraphRunner task_graph_runner
;
5981 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5982 SetupLayersForOpacity(false, 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
, LayersFreeTextures
) {
6003 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6004 TestWebGraphicsContext3D::Create();
6005 TestWebGraphicsContext3D
* context3d
= context
.get();
6006 scoped_ptr
<OutputSurface
> output_surface(
6007 FakeOutputSurface::Create3d(context
.Pass()));
6008 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6010 scoped_ptr
<LayerImpl
> root_layer
=
6011 LayerImpl::Create(host_impl_
->active_tree(), 1);
6012 root_layer
->SetBounds(gfx::Size(10, 10));
6013 root_layer
->SetHasRenderSurface(true);
6015 scoped_refptr
<VideoFrame
> softwareFrame
=
6016 media::VideoFrame::CreateColorFrame(
6017 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
6018 FakeVideoFrameProvider provider
;
6019 provider
.set_frame(softwareFrame
);
6020 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6021 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
6022 video_layer
->SetBounds(gfx::Size(10, 10));
6023 video_layer
->SetDrawsContent(true);
6024 root_layer
->AddChild(video_layer
.Pass());
6026 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
6027 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
6028 io_surface_layer
->SetBounds(gfx::Size(10, 10));
6029 io_surface_layer
->SetDrawsContent(true);
6030 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
6031 root_layer
->AddChild(io_surface_layer
.Pass());
6033 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
6035 EXPECT_EQ(0u, context3d
->NumTextures());
6037 LayerTreeHostImpl::FrameData frame
;
6038 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6039 host_impl_
->DrawLayers(&frame
);
6040 host_impl_
->DidDrawAllLayers(frame
);
6041 host_impl_
->SwapBuffers(frame
);
6043 EXPECT_GT(context3d
->NumTextures(), 0u);
6045 // Kill the layer tree.
6046 host_impl_
->active_tree()->SetRootLayer(
6047 LayerImpl::Create(host_impl_
->active_tree(), 100));
6048 // There should be no textures left in use after.
6049 EXPECT_EQ(0u, context3d
->NumTextures());
6052 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
6054 MOCK_METHOD1(useProgram
, void(GLuint program
));
6055 MOCK_METHOD4(drawElements
, void(GLenum mode
,
6061 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
6062 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
6063 new MockDrawQuadsToFillScreenContext
);
6064 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
6067 LayerTreeSettings settings
= DefaultSettings();
6068 settings
.renderer_settings
.partial_swap_enabled
= false;
6069 CreateHostImpl(settings
,
6070 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
6071 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6072 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
6074 // Verify one quad is drawn when transparent background set is not set.
6075 host_impl_
->active_tree()->set_has_transparent_background(false);
6076 EXPECT_CALL(*mock_context
, useProgram(_
))
6078 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
6080 LayerTreeHostImpl::FrameData frame
;
6081 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6082 host_impl_
->DrawLayers(&frame
);
6083 host_impl_
->DidDrawAllLayers(frame
);
6084 Mock::VerifyAndClearExpectations(&mock_context
);
6086 // Verify no quads are drawn when transparent background is set.
6087 host_impl_
->active_tree()->set_has_transparent_background(true);
6088 host_impl_
->SetFullRootLayerDamage();
6089 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6090 host_impl_
->DrawLayers(&frame
);
6091 host_impl_
->DidDrawAllLayers(frame
);
6092 Mock::VerifyAndClearExpectations(&mock_context
);
6095 class LayerTreeHostImplTestWithDelegatingRenderer
6096 : public LayerTreeHostImplTest
{
6098 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
6099 return FakeOutputSurface::CreateDelegating3d();
6102 void DrawFrameAndTestDamage(const gfx::Rect
& expected_damage
) {
6103 bool expect_to_draw
= !expected_damage
.IsEmpty();
6105 LayerTreeHostImpl::FrameData frame
;
6106 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6108 if (!expect_to_draw
) {
6109 // With no damage, we don't draw, and no quads are created.
6110 ASSERT_EQ(0u, frame
.render_passes
.size());
6112 ASSERT_EQ(1u, frame
.render_passes
.size());
6114 // Verify the damage rect for the root render pass.
6115 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
6116 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
6118 // Verify the root and child layers' quads are generated and not being
6120 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
6122 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
6123 gfx::Rect
expected_child_visible_rect(child
->bounds());
6124 EXPECT_EQ(expected_child_visible_rect
,
6125 root_render_pass
->quad_list
.front()->visible_rect
);
6127 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
6128 gfx::Rect
expected_root_visible_rect(root
->bounds());
6129 EXPECT_EQ(expected_root_visible_rect
,
6130 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
6133 host_impl_
->DrawLayers(&frame
);
6134 host_impl_
->DidDrawAllLayers(frame
);
6135 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
6139 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
6140 scoped_ptr
<SolidColorLayerImpl
> root
=
6141 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6142 root
->SetPosition(gfx::PointF());
6143 root
->SetBounds(gfx::Size(10, 10));
6144 root
->SetDrawsContent(true);
6145 root
->SetHasRenderSurface(true);
6147 // Child layer is in the bottom right corner.
6148 scoped_ptr
<SolidColorLayerImpl
> child
=
6149 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
6150 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
6151 child
->SetBounds(gfx::Size(1, 1));
6152 child
->SetDrawsContent(true);
6153 root
->AddChild(child
.Pass());
6155 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6157 // Draw a frame. In the first frame, the entire viewport should be damaged.
6158 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6159 DrawFrameAndTestDamage(full_frame_damage
);
6161 // The second frame has damage that doesn't touch the child layer. Its quads
6162 // should still be generated.
6163 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
6164 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
6165 DrawFrameAndTestDamage(small_damage
);
6167 // The third frame should have no damage, so no quads should be generated.
6168 gfx::Rect no_damage
;
6169 DrawFrameAndTestDamage(no_damage
);
6172 // TODO(reveman): Remove this test and the ability to prevent on demand raster
6173 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
6174 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
6175 LayerTreeSettings settings
;
6176 CreateHostImpl(settings
, CreateOutputSurface());
6177 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
6180 class FakeMaskLayerImpl
: public LayerImpl
{
6182 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
6184 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
6187 void GetContentsResourceId(ResourceId
* resource_id
,
6188 gfx::Size
* resource_size
) const override
{
6193 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
6194 : LayerImpl(tree_impl
, id
) {}
6197 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
6199 using GLRenderer::ShouldAntialiasQuad
;
6202 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
6203 // Due to precision issues (especially on Android), sometimes far
6204 // away quads can end up thinking they need AA.
6205 float device_scale_factor
= 4.f
/ 3.f
;
6206 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
6207 gfx::Size
root_size(2000, 1000);
6208 gfx::Size device_viewport_size
=
6209 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
6210 host_impl_
->SetViewportSize(device_viewport_size
);
6212 host_impl_
->CreatePendingTree();
6213 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
6216 scoped_ptr
<LayerImpl
> scoped_root
=
6217 LayerImpl::Create(host_impl_
->pending_tree(), 1);
6218 LayerImpl
* root
= scoped_root
.get();
6219 root
->SetHasRenderSurface(true);
6221 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
6223 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
6224 LayerImpl::Create(host_impl_
->pending_tree(), 2);
6225 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
6226 root
->AddChild(scoped_scrolling_layer
.Pass());
6228 gfx::Size
content_layer_bounds(100000, 100);
6229 gfx::Size
pile_tile_size(3000, 3000);
6230 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
6231 pile_tile_size
, content_layer_bounds
));
6233 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
6234 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
6236 LayerImpl
* content_layer
= scoped_content_layer
.get();
6237 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
6238 content_layer
->SetBounds(content_layer_bounds
);
6239 content_layer
->SetDrawsContent(true);
6241 root
->SetBounds(root_size
);
6243 gfx::ScrollOffset
scroll_offset(100000, 0);
6244 scrolling_layer
->SetScrollClipLayer(root
->id());
6245 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
6247 host_impl_
->ActivateSyncTree();
6249 bool update_lcd_text
= false;
6250 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
6251 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
6253 LayerTreeHostImpl::FrameData frame
;
6254 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6256 ASSERT_EQ(1u, frame
.render_passes
.size());
6257 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
6258 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
6260 bool clipped
= false, force_aa
= false;
6261 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
6262 quad
->shared_quad_state
->quad_to_target_transform
,
6263 gfx::QuadF(gfx::RectF(quad
->shared_quad_state
->visible_quad_layer_rect
)),
6265 EXPECT_FALSE(clipped
);
6267 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6268 device_layer_quad
, clipped
, force_aa
);
6269 EXPECT_FALSE(antialiased
);
6271 host_impl_
->DrawLayers(&frame
);
6272 host_impl_
->DidDrawAllLayers(frame
);
6276 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
6278 CompositorFrameMetadataTest()
6279 : swap_buffers_complete_(0) {}
6281 void DidSwapBuffersCompleteOnImplThread() override
{
6282 swap_buffers_complete_
++;
6285 int swap_buffers_complete_
;
6288 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
6289 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
6291 LayerTreeHostImpl::FrameData frame
;
6292 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6293 host_impl_
->DrawLayers(&frame
);
6294 host_impl_
->DidDrawAllLayers(frame
);
6296 CompositorFrameAck ack
;
6297 host_impl_
->ReclaimResources(&ack
);
6298 host_impl_
->DidSwapBuffersComplete();
6299 EXPECT_EQ(swap_buffers_complete_
, 1);
6302 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
6304 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6306 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
6308 return SoftwareOutputDevice::BeginPaint(damage_rect
);
6310 void EndPaint() override
{
6311 SoftwareOutputDevice::EndPaint();
6315 int frames_began_
, frames_ended_
;
6318 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
6319 // No main thread evictions in resourceless software mode.
6320 set_reduce_memory_result(false);
6321 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
6322 EXPECT_TRUE(CreateHostImpl(
6324 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
6325 host_impl_
->SetViewportSize(gfx::Size(50, 50));
6327 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6329 const gfx::Transform external_transform
;
6330 const gfx::Rect external_viewport
;
6331 const gfx::Rect external_clip
;
6332 const bool resourceless_software_draw
= true;
6333 host_impl_
->SetExternalDrawConstraints(external_transform
,
6338 resourceless_software_draw
);
6340 EXPECT_EQ(0, software_device
->frames_began_
);
6341 EXPECT_EQ(0, software_device
->frames_ended_
);
6345 EXPECT_EQ(1, software_device
->frames_began_
);
6346 EXPECT_EQ(1, software_device
->frames_ended_
);
6348 // Call another API method that is likely to hit nullptr in this mode.
6349 scoped_refptr
<base::trace_event::TracedValue
> state
=
6350 make_scoped_refptr(new base::trace_event::TracedValue());
6351 host_impl_
->ActivationStateAsValueInto(state
.get());
6354 TEST_F(LayerTreeHostImplTest
,
6355 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
6356 set_reduce_memory_result(false);
6357 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6358 FakeOutputSurface::CreateSoftware(
6359 make_scoped_ptr(new CountingSoftwareDevice
))));
6361 const gfx::Transform external_transform
;
6362 const gfx::Rect external_viewport
;
6363 const gfx::Rect external_clip
;
6364 const bool resourceless_software_draw
= true;
6365 host_impl_
->SetExternalDrawConstraints(external_transform
,
6370 resourceless_software_draw
);
6372 // SolidColorLayerImpl will be drawn.
6373 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
6374 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6376 // VideoLayerImpl will not be drawn.
6377 FakeVideoFrameProvider provider
;
6378 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6379 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
6380 video_layer
->SetBounds(gfx::Size(10, 10));
6381 video_layer
->SetDrawsContent(true);
6382 root_layer
->AddChild(video_layer
.Pass());
6383 SetupRootLayerImpl(root_layer
.Pass());
6385 LayerTreeHostImpl::FrameData frame
;
6386 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6387 host_impl_
->DrawLayers(&frame
);
6388 host_impl_
->DidDrawAllLayers(frame
);
6390 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
6391 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
6394 // Checks that we have a non-0 default allocation if we pass a context that
6395 // doesn't support memory management extensions.
6396 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
6397 LayerTreeSettings settings
;
6398 host_impl_
= LayerTreeHostImpl::Create(
6399 settings
, this, &proxy_
, &stats_instrumentation_
, &shared_bitmap_manager_
,
6400 &gpu_memory_buffer_manager_
, &task_graph_runner_
, 0);
6402 scoped_ptr
<OutputSurface
> output_surface(
6403 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6404 host_impl_
->InitializeRenderer(output_surface
.Pass());
6405 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
6408 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6409 ASSERT_TRUE(host_impl_
->active_tree());
6411 // RequiresHighResToDraw is set when new output surface is used.
6412 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6414 host_impl_
->ResetRequiresHighResToDraw();
6416 host_impl_
->SetVisible(false);
6417 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6418 host_impl_
->SetVisible(true);
6419 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6420 host_impl_
->SetVisible(false);
6421 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6423 host_impl_
->ResetRequiresHighResToDraw();
6425 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6426 host_impl_
->SetVisible(true);
6427 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6430 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6431 ASSERT_TRUE(host_impl_
->active_tree());
6432 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6434 // RequiresHighResToDraw is set when new output surface is used.
6435 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6437 host_impl_
->ResetRequiresHighResToDraw();
6439 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6440 host_impl_
->SetHasGpuRasterizationTrigger(false);
6441 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6442 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6443 host_impl_
->SetHasGpuRasterizationTrigger(true);
6444 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6445 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6446 host_impl_
->SetHasGpuRasterizationTrigger(false);
6447 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6448 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6450 host_impl_
->ResetRequiresHighResToDraw();
6452 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6453 host_impl_
->SetHasGpuRasterizationTrigger(true);
6454 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6455 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6458 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6460 void SetUp() override
{
6462 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_
,
6463 &shared_bitmap_manager_
, &task_graph_runner_
);
6464 host_impl_
.reset(fake_host_impl_
);
6465 host_impl_
->InitializeRenderer(CreateOutputSurface());
6466 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6469 FakeLayerTreeHostImpl
* fake_host_impl_
;
6472 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6473 fake_host_impl_
->DidModifyTilePriorities();
6474 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6475 fake_host_impl_
->SetVisible(false);
6476 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6479 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6480 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6481 TestWebGraphicsContext3D::Create();
6482 TestWebGraphicsContext3D
* context3d
= context
.get();
6483 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6484 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6486 EXPECT_EQ(0u, context3d
->NumTextures());
6488 UIResourceId ui_resource_id
= 1;
6489 bool is_opaque
= false;
6490 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6491 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6492 EXPECT_EQ(1u, context3d
->NumTextures());
6493 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6496 // Multiple requests with the same id is allowed. The previous texture is
6498 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6499 EXPECT_EQ(1u, context3d
->NumTextures());
6500 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6502 EXPECT_NE(id1
, id2
);
6504 // Deleting invalid UIResourceId is allowed and does not change state.
6505 host_impl_
->DeleteUIResource(-1);
6506 EXPECT_EQ(1u, context3d
->NumTextures());
6508 // Should return zero for invalid UIResourceId. Number of textures should
6510 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6511 EXPECT_EQ(1u, context3d
->NumTextures());
6513 host_impl_
->DeleteUIResource(ui_resource_id
);
6514 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6515 EXPECT_EQ(0u, context3d
->NumTextures());
6517 // Should not change state for multiple deletion on one UIResourceId
6518 host_impl_
->DeleteUIResource(ui_resource_id
);
6519 EXPECT_EQ(0u, context3d
->NumTextures());
6522 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6523 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6524 TestWebGraphicsContext3D::Create();
6525 TestWebGraphicsContext3D
* context3d
= context
.get();
6526 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6528 EXPECT_EQ(0u, context3d
->NumTextures());
6530 gfx::Size
size(4, 4);
6531 // SkImageInfo has no support for ETC1. The |info| below contains the right
6532 // total pixel size for the bitmap but not the right height and width. The
6533 // correct width/height are passed directly to UIResourceBitmap.
6535 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6536 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6537 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6538 pixel_ref
->setImmutable();
6539 UIResourceBitmap
bitmap(pixel_ref
, size
);
6540 UIResourceId ui_resource_id
= 1;
6541 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6542 EXPECT_EQ(1u, context3d
->NumTextures());
6543 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6547 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6550 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6551 scoped_refptr
<TestContextProvider
> context_provider
=
6552 TestContextProvider::Create();
6554 CreateHostImpl(DefaultSettings(),
6555 FakeOutputSurface::Create3d(context_provider
));
6557 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6559 ScopedPtrVector
<CopyOutputRequest
> requests
;
6560 requests
.push_back(CopyOutputRequest::CreateRequest(
6561 base::Bind(&ShutdownReleasesContext_Callback
)));
6563 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6565 LayerTreeHostImpl::FrameData frame
;
6566 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6567 host_impl_
->DrawLayers(&frame
);
6568 host_impl_
->DidDrawAllLayers(frame
);
6570 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6571 // texture in a texture mailbox.
6572 EXPECT_FALSE(context_provider
->HasOneRef());
6573 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6575 host_impl_
= nullptr;
6577 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6578 // released, and the texture deleted.
6579 EXPECT_TRUE(context_provider
->HasOneRef());
6580 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6583 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6584 // When flinging via touch, only the child should scroll (we should not
6586 gfx::Size
surface_size(10, 10);
6587 gfx::Size
content_size(20, 20);
6588 scoped_ptr
<LayerImpl
> root_clip
=
6589 LayerImpl::Create(host_impl_
->active_tree(), 3);
6590 root_clip
->SetHasRenderSurface(true);
6592 scoped_ptr
<LayerImpl
> root
=
6593 CreateScrollableLayer(1, content_size
, root_clip
.get());
6594 root
->SetIsContainerForFixedPositionLayers(true);
6595 scoped_ptr
<LayerImpl
> child
=
6596 CreateScrollableLayer(2, content_size
, root_clip
.get());
6598 root
->AddChild(child
.Pass());
6599 int root_id
= root
->id();
6600 root_clip
->AddChild(root
.Pass());
6602 host_impl_
->SetViewportSize(surface_size
);
6603 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6604 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6606 host_impl_
->active_tree()->DidBecomeActive();
6609 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6610 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6612 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6614 gfx::Vector2d
scroll_delta(0, 100);
6615 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6616 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6618 host_impl_
->ScrollEnd();
6620 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6621 host_impl_
->ProcessScrollDeltas();
6623 // Only the child should have scrolled.
6624 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6625 ExpectNone(*scroll_info
.get(), root_id
);
6629 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6630 // Scroll a child layer beyond its maximum scroll range and make sure the
6631 // the scroll doesn't bubble up to the parent layer.
6632 gfx::Size
surface_size(10, 10);
6633 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6634 root
->SetHasRenderSurface(true);
6635 scoped_ptr
<LayerImpl
> root_scrolling
=
6636 CreateScrollableLayer(2, surface_size
, root
.get());
6638 scoped_ptr
<LayerImpl
> grand_child
=
6639 CreateScrollableLayer(4, surface_size
, root
.get());
6640 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6642 scoped_ptr
<LayerImpl
> child
=
6643 CreateScrollableLayer(3, surface_size
, root
.get());
6644 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6645 child
->AddChild(grand_child
.Pass());
6647 root_scrolling
->AddChild(child
.Pass());
6648 root
->AddChild(root_scrolling
.Pass());
6649 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6650 host_impl_
->active_tree()->DidBecomeActive();
6651 host_impl_
->SetViewportSize(surface_size
);
6654 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6656 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6657 LayerImpl
* grand_child
= child
->children()[0];
6659 gfx::Vector2d
scroll_delta(0, -2);
6660 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6661 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6662 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6664 // The grand child should have scrolled up to its limit.
6665 scroll_info
= host_impl_
->ProcessScrollDeltas();
6666 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6668 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6669 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6671 // The child should have received the bubbled delta, but the locked
6672 // scrolling layer should remain set as the grand child.
6673 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6674 scroll_info
= host_impl_
->ProcessScrollDeltas();
6675 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6677 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6678 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(), scroll_delta
));
6679 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6681 // The first |ScrollBy| after the fling should re-lock the scrolling
6682 // layer to the first layer that scrolled, which is the child.
6683 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6684 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6685 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6687 // The child should have scrolled up to its limit.
6688 scroll_info
= host_impl_
->ProcessScrollDeltas();
6689 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6691 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6692 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(),
6693 scroll_delta
+ scroll_delta
));
6695 // As the locked layer is at it's limit, no further scrolling can occur.
6696 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6697 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6698 host_impl_
->ScrollEnd();
6702 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6703 // When flinging via wheel, the root should eventually scroll (we should
6705 gfx::Size
surface_size(10, 10);
6706 gfx::Size
content_size(20, 20);
6707 scoped_ptr
<LayerImpl
> root_clip
=
6708 LayerImpl::Create(host_impl_
->active_tree(), 3);
6709 root_clip
->SetHasRenderSurface(true);
6710 scoped_ptr
<LayerImpl
> root_scroll
=
6711 CreateScrollableLayer(1, content_size
, root_clip
.get());
6712 int root_scroll_id
= root_scroll
->id();
6713 scoped_ptr
<LayerImpl
> child
=
6714 CreateScrollableLayer(2, content_size
, root_clip
.get());
6716 root_scroll
->AddChild(child
.Pass());
6717 root_clip
->AddChild(root_scroll
.Pass());
6719 host_impl_
->SetViewportSize(surface_size
);
6720 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6721 host_impl_
->active_tree()->DidBecomeActive();
6724 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6725 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6727 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6729 gfx::Vector2d
scroll_delta(0, 100);
6730 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6731 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6733 host_impl_
->ScrollEnd();
6735 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6736 host_impl_
->ProcessScrollDeltas();
6738 // The root should have scrolled.
6739 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6740 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll_id
,
6741 gfx::Vector2d(0, 10)));
6745 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6746 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6747 // we should return SCROLL_UNKNOWN.
6748 gfx::Size
content_size(100, 100);
6749 SetupScrollAndContentsLayers(content_size
);
6751 int scroll_layer_id
= 2;
6752 LayerImpl
* scroll_layer
=
6753 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6754 scroll_layer
->SetDrawsContent(true);
6756 int page_scale_layer_id
= 5;
6757 LayerImpl
* page_scale_layer
=
6758 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6760 int occluder_layer_id
= 6;
6761 scoped_ptr
<LayerImpl
> occluder_layer
=
6762 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6763 occluder_layer
->SetDrawsContent(true);
6764 occluder_layer
->SetBounds(content_size
);
6765 occluder_layer
->SetPosition(gfx::PointF());
6767 // The parent of the occluder is *above* the scroller.
6768 page_scale_layer
->AddChild(occluder_layer
.Pass());
6772 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6773 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6776 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6777 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6778 // is not the first scroller we encounter when walking up from the layer, we
6779 // should also return SCROLL_UNKNOWN.
6780 gfx::Size
content_size(100, 100);
6781 SetupScrollAndContentsLayers(content_size
);
6783 int scroll_layer_id
= 2;
6784 LayerImpl
* scroll_layer
=
6785 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6786 scroll_layer
->SetDrawsContent(true);
6788 int occluder_layer_id
= 6;
6789 scoped_ptr
<LayerImpl
> occluder_layer
=
6790 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6791 occluder_layer
->SetDrawsContent(true);
6792 occluder_layer
->SetBounds(content_size
);
6793 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6795 int child_scroll_clip_layer_id
= 7;
6796 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6797 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6799 int child_scroll_layer_id
= 8;
6800 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6801 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6803 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6805 child_scroll
->AddChild(occluder_layer
.Pass());
6806 scroll_layer
->AddChild(child_scroll
.Pass());
6810 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6811 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6814 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6815 gfx::Size
content_size(100, 100);
6816 SetupScrollAndContentsLayers(content_size
);
6818 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6820 int scroll_layer_id
= 2;
6821 LayerImpl
* scroll_layer
=
6822 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6824 int child_scroll_layer_id
= 7;
6825 scoped_ptr
<LayerImpl
> child_scroll
=
6826 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6827 child_scroll
->SetDrawsContent(false);
6829 scroll_layer
->AddChild(child_scroll
.Pass());
6833 // We should not have scrolled |child_scroll| even though we technically "hit"
6834 // it. The reason for this is that if the scrolling the scroll would not move
6835 // any layer that is a drawn RSLL member, then we can ignore the hit.
6837 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6838 // started scrolling the inner viewport.
6839 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6840 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6842 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6845 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6846 gfx::Size
content_size(100, 100);
6847 SetupScrollAndContentsLayers(content_size
);
6849 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6850 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6852 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6853 CreateScrollableLayer(7, content_size
, root
);
6854 invisible_scroll_layer
->SetDrawsContent(false);
6856 scoped_ptr
<LayerImpl
> child_layer
=
6857 LayerImpl::Create(host_impl_
->active_tree(), 8);
6858 child_layer
->SetDrawsContent(false);
6860 scoped_ptr
<LayerImpl
> grand_child_layer
=
6861 LayerImpl::Create(host_impl_
->active_tree(), 9);
6862 grand_child_layer
->SetDrawsContent(true);
6863 grand_child_layer
->SetBounds(content_size
);
6864 // Move the grand child so it's not hit by our test point.
6865 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6867 child_layer
->AddChild(grand_child_layer
.Pass());
6868 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6869 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6873 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6874 // a descendant which is a drawn RSLL member.
6875 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6876 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6878 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6881 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6882 // This test case is very similar to the one above with one key difference:
6883 // the invisible scroller has a scroll child that is indeed draw contents.
6884 // If we attempt to initiate a gesture scroll off of the visible scroll child
6885 // we should still start the scroll child.
6886 gfx::Size
content_size(100, 100);
6887 SetupScrollAndContentsLayers(content_size
);
6889 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6891 int scroll_layer_id
= 2;
6892 LayerImpl
* scroll_layer
=
6893 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6895 int scroll_child_id
= 6;
6896 scoped_ptr
<LayerImpl
> scroll_child
=
6897 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6898 scroll_child
->SetDrawsContent(true);
6899 scroll_child
->SetBounds(content_size
);
6900 // Move the scroll child so it's not hit by our test point.
6901 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6903 int invisible_scroll_layer_id
= 7;
6904 scoped_ptr
<LayerImpl
> invisible_scroll
=
6905 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6906 invisible_scroll
->SetDrawsContent(false);
6908 int container_id
= 8;
6909 scoped_ptr
<LayerImpl
> container
=
6910 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6912 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6913 scroll_children
->insert(scroll_child
.get());
6914 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6916 scroll_child
->SetScrollParent(invisible_scroll
.get());
6918 container
->AddChild(invisible_scroll
.Pass());
6919 container
->AddChild(scroll_child
.Pass());
6921 scroll_layer
->AddChild(container
.Pass());
6925 // We should have scrolled |child_scroll| even though it is invisible.
6926 // The reason for this is that if the scrolling the scroll would move a layer
6927 // that is a drawn RSLL member, then we should accept this hit.
6928 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6929 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6931 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6934 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6935 // to CompositorFrameMetadata after SwapBuffers();
6936 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6937 scoped_ptr
<SolidColorLayerImpl
> root
=
6938 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6939 root
->SetPosition(gfx::PointF());
6940 root
->SetBounds(gfx::Size(10, 10));
6941 root
->SetDrawsContent(true);
6942 root
->SetHasRenderSurface(true);
6944 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6946 FakeOutputSurface
* fake_output_surface
=
6947 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6949 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6950 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6951 EXPECT_TRUE(metadata_latency_before
.empty());
6953 ui::LatencyInfo latency_info
;
6954 latency_info
.AddLatencyNumber(
6955 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6956 scoped_ptr
<SwapPromise
> swap_promise(
6957 new LatencyInfoSwapPromise(latency_info
));
6958 host_impl_
->active_tree()->QueuePinnedSwapPromise(swap_promise
.Pass());
6959 host_impl_
->SetNeedsRedraw();
6961 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6962 LayerTreeHostImpl::FrameData frame
;
6963 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6964 host_impl_
->DrawLayers(&frame
);
6965 host_impl_
->DidDrawAllLayers(frame
);
6966 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6968 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6969 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6970 EXPECT_EQ(1u, metadata_latency_after
.size());
6971 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6972 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6975 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6976 int root_layer_id
= 1;
6977 scoped_ptr
<SolidColorLayerImpl
> root
=
6978 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6979 root
->SetPosition(gfx::PointF());
6980 root
->SetBounds(gfx::Size(10, 10));
6981 root
->SetDrawsContent(true);
6982 root
->SetHasRenderSurface(true);
6984 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6986 // Ensure the default frame selection bounds are empty.
6987 FakeOutputSurface
* fake_output_surface
=
6988 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6989 const ViewportSelection
& selection_before
=
6990 fake_output_surface
->last_sent_frame().metadata
.selection
;
6991 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
6992 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
6994 // Plumb the layer-local selection bounds.
6995 gfx::PointF
selection_top(5, 0);
6996 gfx::PointF
selection_bottom(5, 5);
6997 LayerSelection selection
;
6998 selection
.start
.type
= SELECTION_BOUND_CENTER
;
6999 selection
.start
.layer_id
= root_layer_id
;
7000 selection
.start
.edge_bottom
= selection_bottom
;
7001 selection
.start
.edge_top
= selection_top
;
7002 selection
.end
= selection
.start
;
7003 host_impl_
->active_tree()->RegisterSelection(selection
);
7005 // Trigger a draw-swap sequence.
7006 host_impl_
->SetNeedsRedraw();
7008 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
7009 LayerTreeHostImpl::FrameData frame
;
7010 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
7011 host_impl_
->DrawLayers(&frame
);
7012 host_impl_
->DidDrawAllLayers(frame
);
7013 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
7015 // Ensure the selection bounds have propagated to the frame metadata.
7016 const ViewportSelection
& selection_after
=
7017 fake_output_surface
->last_sent_frame().metadata
.selection
;
7018 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
7019 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
7020 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
7021 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
7022 EXPECT_TRUE(selection_after
.start
.visible
);
7023 EXPECT_TRUE(selection_after
.start
.visible
);
7026 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
7028 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
7029 LayerTreeHostImpl
* layer_tree_host_impl
,
7030 int* set_needs_commit_count
,
7031 int* set_needs_redraw_count
,
7032 int* forward_to_main_count
)
7033 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
7034 set_needs_commit_count_(set_needs_commit_count
),
7035 set_needs_redraw_count_(set_needs_redraw_count
),
7036 forward_to_main_count_(forward_to_main_count
) {}
7038 ~SimpleSwapPromiseMonitor() override
{}
7040 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
7042 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
7044 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
7045 (*forward_to_main_count_
)++;
7049 int* set_needs_commit_count_
;
7050 int* set_needs_redraw_count_
;
7051 int* forward_to_main_count_
;
7054 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
7055 int set_needs_commit_count
= 0;
7056 int set_needs_redraw_count
= 0;
7057 int forward_to_main_count
= 0;
7060 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7061 new SimpleSwapPromiseMonitor(NULL
,
7063 &set_needs_commit_count
,
7064 &set_needs_redraw_count
,
7065 &forward_to_main_count
));
7066 host_impl_
->SetNeedsRedraw();
7067 EXPECT_EQ(0, set_needs_commit_count
);
7068 EXPECT_EQ(1, set_needs_redraw_count
);
7069 EXPECT_EQ(0, forward_to_main_count
);
7072 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7074 host_impl_
->SetNeedsRedraw();
7075 EXPECT_EQ(0, set_needs_commit_count
);
7076 EXPECT_EQ(1, set_needs_redraw_count
);
7077 EXPECT_EQ(0, forward_to_main_count
);
7080 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7081 new SimpleSwapPromiseMonitor(NULL
,
7083 &set_needs_commit_count
,
7084 &set_needs_redraw_count
,
7085 &forward_to_main_count
));
7086 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
7087 EXPECT_EQ(0, set_needs_commit_count
);
7088 EXPECT_EQ(2, set_needs_redraw_count
);
7089 EXPECT_EQ(0, forward_to_main_count
);
7093 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7094 new SimpleSwapPromiseMonitor(NULL
,
7096 &set_needs_commit_count
,
7097 &set_needs_redraw_count
,
7098 &forward_to_main_count
));
7099 // Empty damage rect won't signal the monitor.
7100 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
7101 EXPECT_EQ(0, set_needs_commit_count
);
7102 EXPECT_EQ(2, set_needs_redraw_count
);
7103 EXPECT_EQ(0, forward_to_main_count
);
7107 set_needs_commit_count
= 0;
7108 set_needs_redraw_count
= 0;
7109 forward_to_main_count
= 0;
7110 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7111 new SimpleSwapPromiseMonitor(NULL
,
7113 &set_needs_commit_count
,
7114 &set_needs_redraw_count
,
7115 &forward_to_main_count
));
7116 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7118 // Scrolling normally should not trigger any forwarding.
7119 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7120 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7122 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7123 host_impl_
->ScrollEnd();
7125 EXPECT_EQ(0, set_needs_commit_count
);
7126 EXPECT_EQ(1, set_needs_redraw_count
);
7127 EXPECT_EQ(0, forward_to_main_count
);
7129 // Scrolling with a scroll handler should defer the swap to the main
7131 scroll_layer
->SetHaveScrollEventHandlers(true);
7132 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7133 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7135 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7136 host_impl_
->ScrollEnd();
7138 EXPECT_EQ(0, set_needs_commit_count
);
7139 EXPECT_EQ(2, set_needs_redraw_count
);
7140 EXPECT_EQ(1, forward_to_main_count
);
7144 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
7146 void SetUp() override
{
7147 LayerTreeSettings settings
= DefaultSettings();
7148 CreateHostImpl(settings
, CreateOutputSurface());
7149 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
7150 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
7151 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
7155 static const int top_controls_height_
;
7158 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
7160 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
7161 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7162 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7163 BeginFrameArgs begin_frame_args
=
7164 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7165 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7166 host_impl_
->Animate();
7167 EXPECT_FALSE(did_request_redraw_
);
7168 host_impl_
->DidFinishImplFrame();
7171 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
7172 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7173 EXPECT_FALSE(did_request_redraw_
);
7174 host_impl_
->CreatePendingTree();
7175 host_impl_
->sync_tree()->set_top_controls_height(100);
7176 host_impl_
->ActivateSyncTree();
7177 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
7180 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7181 TopControlsStayFullyVisibleOnHeightChange
) {
7182 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7183 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7185 host_impl_
->CreatePendingTree();
7186 host_impl_
->sync_tree()->set_top_controls_height(0);
7187 host_impl_
->ActivateSyncTree();
7188 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7190 host_impl_
->CreatePendingTree();
7191 host_impl_
->sync_tree()->set_top_controls_height(50);
7192 host_impl_
->ActivateSyncTree();
7193 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7196 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
7197 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7198 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7199 host_impl_
->DidChangeTopControlsPosition();
7200 EXPECT_TRUE(did_request_animate_
);
7201 EXPECT_TRUE(did_request_redraw_
);
7204 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
7205 InputHandlerScrollResult result
;
7206 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7207 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7208 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7209 BOTH
, SHOWN
, false);
7212 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7213 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7214 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7215 EXPECT_EQ(gfx::Vector2dF().ToString(),
7216 scroll_layer
->CurrentScrollOffset().ToString());
7218 // Scroll just the top controls and verify that the scroll succeeds.
7219 const float residue
= 10;
7220 float offset
= top_controls_height_
- residue
;
7221 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7222 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7223 EXPECT_TRUE(result
.did_scroll
);
7224 EXPECT_FLOAT_EQ(-offset
,
7225 host_impl_
->top_controls_manager()->ControlsTopOffset());
7226 EXPECT_EQ(gfx::Vector2dF().ToString(),
7227 scroll_layer
->CurrentScrollOffset().ToString());
7229 // Scroll across the boundary
7230 const float content_scroll
= 20;
7231 offset
= residue
+ content_scroll
;
7232 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7233 EXPECT_TRUE(result
.did_scroll
);
7234 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7235 EXPECT_EQ(-top_controls_height_
,
7236 host_impl_
->top_controls_manager()->ControlsTopOffset());
7237 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
7238 scroll_layer
->CurrentScrollOffset().ToString());
7240 // Now scroll back to the top of the content
7241 offset
= -content_scroll
;
7242 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7243 EXPECT_TRUE(result
.did_scroll
);
7244 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7245 EXPECT_EQ(-top_controls_height_
,
7246 host_impl_
->top_controls_manager()->ControlsTopOffset());
7247 EXPECT_EQ(gfx::Vector2dF().ToString(),
7248 scroll_layer
->CurrentScrollOffset().ToString());
7250 // And scroll the top controls completely into view
7251 offset
= -top_controls_height_
;
7252 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7253 EXPECT_TRUE(result
.did_scroll
);
7254 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7255 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7256 EXPECT_EQ(gfx::Vector2dF().ToString(),
7257 scroll_layer
->CurrentScrollOffset().ToString());
7259 // And attempt to scroll past the end
7260 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7261 EXPECT_FALSE(result
.did_scroll
);
7262 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, -50));
7263 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7264 EXPECT_EQ(gfx::Vector2dF().ToString(),
7265 scroll_layer
->CurrentScrollOffset().ToString());
7267 host_impl_
->ScrollEnd();
7270 TEST_F(LayerTreeHostImplWithTopControlsTest
, WheelUnhandledByTopControls
) {
7271 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7272 host_impl_
->SetViewportSize(gfx::Size(50, 100));
7273 host_impl_
->active_tree()->set_top_controls_shrink_blink_size(true);
7274 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7278 LayerImpl
* viewport_layer
= host_impl_
->InnerViewportScrollLayer();
7280 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7281 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7282 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7283 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer
->CurrentScrollOffset());
7285 // Wheel scrolls should not affect the top controls, and should pass
7286 // directly through to the viewport.
7287 const float delta
= top_controls_height_
;
7289 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7290 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7291 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
),
7292 viewport_layer
->CurrentScrollOffset());
7295 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7296 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7297 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
* 2),
7298 viewport_layer
->CurrentScrollOffset());
7301 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
7302 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7303 host_impl_
->SetViewportSize(gfx::Size(100, 200));
7304 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7305 BOTH
, SHOWN
, false);
7308 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7309 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7310 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7311 EXPECT_EQ(gfx::Vector2dF().ToString(),
7312 scroll_layer
->CurrentScrollOffset().ToString());
7314 // Scroll the top controls partially.
7315 const float residue
= 35;
7316 float offset
= top_controls_height_
- residue
;
7318 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7319 EXPECT_FLOAT_EQ(-offset
,
7320 host_impl_
->top_controls_manager()->ControlsTopOffset());
7321 EXPECT_EQ(gfx::Vector2dF().ToString(),
7322 scroll_layer
->CurrentScrollOffset().ToString());
7324 did_request_redraw_
= false;
7325 did_request_animate_
= false;
7326 did_request_commit_
= false;
7328 // End the scroll while the controls are still offset from their limit.
7329 host_impl_
->ScrollEnd();
7330 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7331 EXPECT_TRUE(did_request_animate_
);
7332 EXPECT_TRUE(did_request_redraw_
);
7333 EXPECT_FALSE(did_request_commit_
);
7335 // The top controls should properly animate until finished, despite the scroll
7336 // offset being at the origin.
7337 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7338 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7339 while (did_request_animate_
) {
7340 did_request_redraw_
= false;
7341 did_request_animate_
= false;
7342 did_request_commit_
= false;
7345 host_impl_
->top_controls_manager()->ControlsTopOffset();
7347 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7348 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7349 host_impl_
->Animate();
7350 EXPECT_EQ(gfx::Vector2dF().ToString(),
7351 scroll_layer
->CurrentScrollOffset().ToString());
7354 host_impl_
->top_controls_manager()->ControlsTopOffset();
7356 // No commit is needed as the controls are animating the content offset,
7357 // not the scroll offset.
7358 EXPECT_FALSE(did_request_commit_
);
7360 if (new_offset
!= old_offset
)
7361 EXPECT_TRUE(did_request_redraw_
);
7363 if (new_offset
!= 0) {
7364 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
7365 EXPECT_TRUE(did_request_animate_
);
7367 host_impl_
->DidFinishImplFrame();
7369 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7372 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
7373 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7374 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7375 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7376 BOTH
, SHOWN
, false);
7377 float initial_scroll_offset
= 50;
7378 scroll_layer
->PushScrollOffsetFromMainThread(
7379 gfx::ScrollOffset(0, initial_scroll_offset
));
7382 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7383 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7384 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7385 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7386 scroll_layer
->CurrentScrollOffset().ToString());
7388 // Scroll the top controls partially.
7389 const float residue
= 15;
7390 float offset
= top_controls_height_
- residue
;
7392 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7393 EXPECT_FLOAT_EQ(-offset
,
7394 host_impl_
->top_controls_manager()->ControlsTopOffset());
7395 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7396 scroll_layer
->CurrentScrollOffset().ToString());
7398 did_request_redraw_
= false;
7399 did_request_animate_
= false;
7400 did_request_commit_
= false;
7402 // End the scroll while the controls are still offset from the limit.
7403 host_impl_
->ScrollEnd();
7404 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7405 EXPECT_TRUE(did_request_animate_
);
7406 EXPECT_TRUE(did_request_redraw_
);
7407 EXPECT_FALSE(did_request_commit_
);
7409 // Animate the top controls to the limit.
7410 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7411 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7412 while (did_request_animate_
) {
7413 did_request_redraw_
= false;
7414 did_request_animate_
= false;
7415 did_request_commit_
= false;
7418 host_impl_
->top_controls_manager()->ControlsTopOffset();
7420 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7421 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7422 host_impl_
->Animate();
7425 host_impl_
->top_controls_manager()->ControlsTopOffset();
7427 if (new_offset
!= old_offset
) {
7428 EXPECT_TRUE(did_request_redraw_
);
7429 EXPECT_TRUE(did_request_commit_
);
7431 host_impl_
->DidFinishImplFrame();
7433 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7434 EXPECT_EQ(-top_controls_height_
,
7435 host_impl_
->top_controls_manager()->ControlsTopOffset());
7438 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7439 TopControlsAnimationAfterMainThreadFlingStopped
) {
7440 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7441 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7442 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7444 float initial_scroll_offset
= 50;
7445 scroll_layer
->PushScrollOffsetFromMainThread(
7446 gfx::ScrollOffset(0, initial_scroll_offset
));
7449 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7450 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7451 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7452 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7453 scroll_layer
->CurrentScrollOffset().ToString());
7455 // Scroll the top controls partially.
7456 const float residue
= 15;
7457 float offset
= top_controls_height_
- residue
;
7459 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7460 EXPECT_FLOAT_EQ(-offset
,
7461 host_impl_
->top_controls_manager()->ControlsTopOffset());
7462 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7463 scroll_layer
->CurrentScrollOffset().ToString());
7465 did_request_redraw_
= false;
7466 did_request_animate_
= false;
7467 did_request_commit_
= false;
7469 // End the fling while the controls are still offset from the limit.
7470 host_impl_
->MainThreadHasStoppedFlinging();
7471 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7472 EXPECT_TRUE(did_request_animate_
);
7473 EXPECT_TRUE(did_request_redraw_
);
7474 EXPECT_FALSE(did_request_commit_
);
7476 // Animate the top controls to the limit.
7477 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7478 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7479 while (did_request_animate_
) {
7480 did_request_redraw_
= false;
7481 did_request_animate_
= false;
7482 did_request_commit_
= false;
7484 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7486 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7487 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7488 host_impl_
->Animate();
7490 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7492 if (new_offset
!= old_offset
) {
7493 EXPECT_TRUE(did_request_redraw_
);
7494 EXPECT_TRUE(did_request_commit_
);
7496 host_impl_
->DidFinishImplFrame();
7498 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7499 EXPECT_EQ(-top_controls_height_
,
7500 host_impl_
->top_controls_manager()->ControlsTopOffset());
7503 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7504 TopControlsScrollDeltaInOverScroll
) {
7505 // Verifies that the overscroll delta should not have accumulated in
7506 // the top controls if we do a hide and show without releasing finger.
7508 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7509 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7510 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7514 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7515 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7516 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7520 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7521 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7522 EXPECT_EQ(gfx::Vector2dF().ToString(),
7523 scroll_layer
->CurrentScrollOffset().ToString());
7526 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7527 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7528 scroll_layer
->CurrentScrollOffset().ToString());
7531 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7533 // Should have fully scrolled
7534 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7535 scroll_layer
->CurrentScrollOffset().ToString());
7537 float overscrollamount
= 10;
7539 // Overscroll the content
7541 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7543 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7544 scroll_layer
->CurrentScrollOffset().ToString());
7545 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7546 host_impl_
->accumulated_root_overscroll().ToString());
7548 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7550 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7551 scroll_layer
->CurrentScrollOffset().ToString());
7552 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7555 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7556 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7557 scroll_layer
->CurrentScrollOffset().ToString());
7559 // Top controls should be fully visible
7560 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7562 host_impl_
->ScrollEnd();
7565 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7567 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7568 const gfx::Size
& outer_viewport
,
7569 const gfx::Size
& inner_viewport
) {
7570 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7571 const int kOuterViewportClipLayerId
= 6;
7572 const int kOuterViewportScrollLayerId
= 7;
7573 const int kInnerViewportScrollLayerId
= 2;
7574 const int kInnerViewportClipLayerId
= 4;
7575 const int kPageScaleLayerId
= 5;
7577 scoped_ptr
<LayerImpl
> inner_scroll
=
7578 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7579 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7580 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7582 scoped_ptr
<LayerImpl
> inner_clip
=
7583 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7584 inner_clip
->SetBounds(inner_viewport
);
7586 scoped_ptr
<LayerImpl
> page_scale
=
7587 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7589 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7590 inner_scroll
->SetBounds(outer_viewport
);
7591 inner_scroll
->SetPosition(gfx::PointF());
7593 scoped_ptr
<LayerImpl
> outer_clip
=
7594 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7595 outer_clip
->SetBounds(outer_viewport
);
7596 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7598 scoped_ptr
<LayerImpl
> outer_scroll
=
7599 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7600 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7601 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7602 outer_scroll
->SetBounds(content_size
);
7603 outer_scroll
->SetPosition(gfx::PointF());
7605 scoped_ptr
<LayerImpl
> contents
=
7606 LayerImpl::Create(layer_tree_impl
, 8);
7607 contents
->SetDrawsContent(true);
7608 contents
->SetBounds(content_size
);
7609 contents
->SetPosition(gfx::PointF());
7611 outer_scroll
->AddChild(contents
.Pass());
7612 outer_clip
->AddChild(outer_scroll
.Pass());
7613 inner_scroll
->AddChild(outer_clip
.Pass());
7614 page_scale
->AddChild(inner_scroll
.Pass());
7615 inner_clip
->AddChild(page_scale
.Pass());
7617 inner_clip
->SetHasRenderSurface(true);
7618 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7619 layer_tree_impl
->SetViewportLayersFromIds(
7620 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7621 kOuterViewportScrollLayerId
);
7623 host_impl_
->active_tree()->DidBecomeActive();
7627 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7628 gfx::Size content_size
= gfx::Size(100, 160);
7629 gfx::Size outer_viewport
= gfx::Size(50, 80);
7630 gfx::Size inner_viewport
= gfx::Size(25, 40);
7632 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7634 TestScrollOffsetDelegate scroll_delegate
;
7635 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7637 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7638 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7641 gfx::ScrollOffset inner_expected
;
7642 gfx::ScrollOffset outer_expected
;
7643 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7644 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7646 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7648 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
7649 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7650 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7652 // Outer viewport scrolls first. Then the rest is applied to the inner
7654 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7655 inner_scroll
->CurrentScrollOffset());
7656 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7657 outer_scroll
->CurrentScrollOffset());
7661 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7662 gfx::Size content_size
= gfx::Size(200, 320);
7663 gfx::Size outer_viewport
= gfx::Size(100, 160);
7664 gfx::Size inner_viewport
= gfx::Size(50, 80);
7666 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7668 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7669 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7672 gfx::Vector2dF inner_expected
;
7673 gfx::Vector2dF outer_expected
;
7674 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7675 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7677 // Scrolling the viewport always sets the outer scroll layer as the
7678 // currently scrolling layer.
7679 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7680 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7681 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7682 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7683 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7685 gfx::Vector2d
scroll_delta(inner_viewport
.width() / 2.f
,
7686 inner_viewport
.height() / 2.f
);
7687 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7688 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7689 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), outer_scroll
);
7691 host_impl_
->ScrollEnd();
7692 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7694 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7695 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7697 // Fling past the inner viewport boundry, make sure outer viewport scrolls.
7698 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7699 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7700 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7701 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7702 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7704 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7705 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7706 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7708 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7709 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7710 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7712 host_impl_
->ScrollEnd();
7713 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7715 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7716 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7720 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7721 DiagonalScrollBubblesPerfectlyToInner
) {
7722 gfx::Size content_size
= gfx::Size(200, 320);
7723 gfx::Size outer_viewport
= gfx::Size(100, 160);
7724 gfx::Size inner_viewport
= gfx::Size(50, 80);
7726 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7728 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7729 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7732 gfx::Vector2dF inner_expected
;
7733 gfx::Vector2dF outer_expected
;
7734 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7735 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7737 // Make sure the scroll goes to the inner viewport first.
7738 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7739 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7740 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7741 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7742 InputHandler::GESTURE
));
7744 // Scroll near the edge of the outer viewport.
7745 gfx::Vector2d
scroll_delta(inner_viewport
.width() / 2.f
,
7746 inner_viewport
.height() / 2.f
);
7747 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7748 inner_expected
+= scroll_delta
;
7749 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7750 InputHandler::GESTURE
));
7752 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7753 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7755 // Now diagonal scroll across the outer viewport boundary in a single event.
7756 // The entirety of the scroll should be consumed, as bubbling between inner
7757 // and outer viewport layers is perfect.
7758 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7759 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7760 InputHandler::GESTURE
));
7761 outer_expected
+= scroll_delta
;
7762 inner_expected
+= scroll_delta
;
7763 host_impl_
->ScrollEnd();
7764 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7765 gfx::Point(), InputHandler::GESTURE
));
7767 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7768 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7772 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7773 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7774 gfx::Size content_size
= gfx::Size(100, 160);
7775 gfx::Size outer_viewport
= gfx::Size(50, 80);
7776 gfx::Size inner_viewport
= gfx::Size(25, 40);
7778 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7780 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7781 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7783 scoped_ptr
<LayerImpl
> child
=
7784 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7785 LayerImpl
* child_scroll
= child
.get();
7786 outer_scroll
->children()[0]->AddChild(child
.Pass());
7790 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7792 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7793 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7794 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7795 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7796 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7797 InputHandler::GESTURE
));
7799 // The child should have scrolled up to its limit.
7800 scroll_info
= host_impl_
->ProcessScrollDeltas();
7801 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7803 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7804 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7806 // The first |ScrollBy| after the fling should re-lock the scrolling
7807 // layer to the first layer that scrolled, the inner viewport scroll layer.
7808 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7809 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7810 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7811 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7812 InputHandler::GESTURE
));
7814 // The inner viewport should have scrolled up to its limit.
7815 scroll_info
= host_impl_
->ProcessScrollDeltas();
7816 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7818 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7820 ScrollInfoContains(*scroll_info
, inner_scroll
->id(), scroll_delta
));
7822 // As the locked layer is at its limit, no further scrolling can occur.
7823 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7824 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7825 host_impl_
->ScrollEnd();
7826 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7827 gfx::Point(), InputHandler::GESTURE
));
7831 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7832 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest
) {
7833 gfx::Size content_size
= gfx::Size(100, 160);
7834 gfx::Size outer_viewport
= gfx::Size(50, 80);
7835 gfx::Size inner_viewport
= gfx::Size(25, 40);
7837 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7839 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7840 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7842 scoped_ptr
<LayerImpl
> child
=
7843 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7844 LayerImpl
* child_scroll
= child
.get();
7845 outer_scroll
->children()[0]->AddChild(child
.Pass());
7849 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7850 host_impl_
->RootScrollBegin(InputHandler::GESTURE
));
7851 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7852 host_impl_
->ScrollEnd();
7853 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7854 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7855 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7856 host_impl_
->ScrollEnd();
7859 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7860 NoOverscrollWhenInnerViewportCantScroll
) {
7861 InputHandlerScrollResult scroll_result
;
7862 gfx::Size content_size
= gfx::Size(100, 160);
7863 gfx::Size outer_viewport
= gfx::Size(50, 80);
7864 gfx::Size inner_viewport
= gfx::Size(25, 40);
7865 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7868 // Make inner viewport unscrollable.
7869 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7870 inner_scroll
->set_user_scrollable_horizontal(false);
7871 inner_scroll
->set_user_scrollable_vertical(false);
7873 // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
7874 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7875 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7876 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7877 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
7878 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7880 // When inner viewport is unscrollable, a fling gives zero overscroll.
7881 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
7882 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
7885 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7887 void SetUp() override
{
7888 LayerTreeSettings settings
= DefaultSettings();
7889 settings
.max_memory_for_prepaint_percentage
= 50;
7890 CreateHostImpl(settings
, CreateOutputSurface());
7894 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7895 // Set up a memory policy and percentages which could cause
7896 // 32-bit integer overflows.
7897 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7899 // Verify implicit limits are calculated correctly with no overflows
7900 host_impl_
->SetMemoryPolicy(mem_policy
);
7901 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7902 300u * 1024u * 1024u);
7903 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7904 150u * 1024u * 1024u);
7907 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7908 const gfx::Size
layer_size(100, 100);
7909 gfx::Transform external_transform
;
7910 const gfx::Rect
external_viewport(layer_size
);
7911 const gfx::Rect
external_clip(layer_size
);
7912 const bool resourceless_software_draw
= false;
7913 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7915 host_impl_
->SetExternalDrawConstraints(external_transform
,
7920 resourceless_software_draw
);
7922 EXPECT_TRANSFORMATION_MATRIX_EQ(
7923 external_transform
, layer
->draw_properties().target_space_transform
);
7925 external_transform
.Translate(20, 20);
7926 host_impl_
->SetExternalDrawConstraints(external_transform
,
7931 resourceless_software_draw
);
7933 EXPECT_TRANSFORMATION_MATRIX_EQ(
7934 external_transform
, layer
->draw_properties().target_space_transform
);
7937 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7938 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7941 base::TimeTicks start_time
=
7942 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7944 BeginFrameArgs begin_frame_args
=
7945 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7947 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7948 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7950 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7952 begin_frame_args
.frame_time
= start_time
;
7953 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7954 host_impl_
->Animate();
7955 host_impl_
->UpdateAnimationState(true);
7957 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7958 host_impl_
->DidFinishImplFrame();
7960 begin_frame_args
.frame_time
=
7961 start_time
+ base::TimeDelta::FromMilliseconds(50);
7962 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7963 host_impl_
->Animate();
7964 host_impl_
->UpdateAnimationState(true);
7966 float y
= scrolling_layer
->CurrentScrollOffset().y();
7967 EXPECT_TRUE(y
> 1 && y
< 49);
7970 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7971 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7972 host_impl_
->DidFinishImplFrame();
7974 begin_frame_args
.frame_time
=
7975 start_time
+ base::TimeDelta::FromMilliseconds(200);
7976 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7977 host_impl_
->Animate();
7978 host_impl_
->UpdateAnimationState(true);
7980 y
= scrolling_layer
->CurrentScrollOffset().y();
7981 EXPECT_TRUE(y
> 50 && y
< 100);
7982 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7983 host_impl_
->DidFinishImplFrame();
7985 begin_frame_args
.frame_time
=
7986 start_time
+ base::TimeDelta::FromMilliseconds(250);
7987 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7988 host_impl_
->Animate();
7989 host_impl_
->UpdateAnimationState(true);
7991 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7992 scrolling_layer
->CurrentScrollOffset());
7993 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7994 host_impl_
->DidFinishImplFrame();
7997 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
7998 TEST_F(LayerTreeHostImplTimelinesTest
, ScrollAnimated
) {
7999 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8002 base::TimeTicks start_time
=
8003 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8005 BeginFrameArgs begin_frame_args
=
8006 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8008 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8009 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8011 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
8013 begin_frame_args
.frame_time
= start_time
;
8014 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8015 host_impl_
->Animate();
8016 host_impl_
->UpdateAnimationState(true);
8018 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
8019 host_impl_
->DidFinishImplFrame();
8021 begin_frame_args
.frame_time
=
8022 start_time
+ base::TimeDelta::FromMilliseconds(50);
8023 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8024 host_impl_
->Animate();
8025 host_impl_
->UpdateAnimationState(true);
8027 float y
= scrolling_layer
->CurrentScrollOffset().y();
8028 EXPECT_TRUE(y
> 1 && y
< 49);
8031 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8032 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8033 host_impl_
->DidFinishImplFrame();
8035 begin_frame_args
.frame_time
=
8036 start_time
+ base::TimeDelta::FromMilliseconds(200);
8037 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8038 host_impl_
->Animate();
8039 host_impl_
->UpdateAnimationState(true);
8041 y
= scrolling_layer
->CurrentScrollOffset().y();
8042 EXPECT_TRUE(y
> 50 && y
< 100);
8043 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
8044 host_impl_
->DidFinishImplFrame();
8046 begin_frame_args
.frame_time
=
8047 start_time
+ base::TimeDelta::FromMilliseconds(250);
8048 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8049 host_impl_
->Animate();
8050 host_impl_
->UpdateAnimationState(true);
8052 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8053 scrolling_layer
->CurrentScrollOffset());
8054 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
8055 host_impl_
->DidFinishImplFrame();
8058 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
8059 host_impl_
->CreatePendingTree();
8061 Region empty_invalidation
;
8062 scoped_refptr
<RasterSource
> pile_with_tiles(
8063 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
8064 gfx::Size(10, 10)));
8066 scoped_ptr
<FakePictureLayerImpl
> layer
=
8067 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
8068 layer
->SetBounds(gfx::Size(10, 10));
8069 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
8070 layer
->SetDrawsContent(true);
8071 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
8072 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
8073 layer
->tilings()->tiling_at(0)->set_resolution(
8074 TileResolution::HIGH_RESOLUTION
);
8075 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
8076 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
8077 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
8078 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
8080 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
8081 host_impl_
->pending_tree()->root_layer());
8083 root_layer
->set_has_valid_tile_priorities(true);
8084 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
8085 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8086 RasterTilePriorityQueue::Type::ALL
);
8087 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
8089 root_layer
->set_has_valid_tile_priorities(false);
8090 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
8091 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8092 RasterTilePriorityQueue::Type::ALL
);
8093 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
8096 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
8097 host_impl_
->CreatePendingTree();
8098 host_impl_
->ActivateSyncTree();
8099 host_impl_
->CreatePendingTree();
8101 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
8103 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
8104 FakePictureLayerImpl::Create(pending_tree
, 10);
8105 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
8106 pending_tree
->SetRootLayer(pending_layer
.Pass());
8107 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
8109 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
8110 pending_tree
->DidBecomeActive();
8111 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8113 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
8114 FakePictureLayerImpl::Create(pending_tree
, 11);
8115 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
8116 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
8117 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
8119 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8120 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
8121 pending_tree
->DidBecomeActive();
8122 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8123 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8125 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
8126 FakePictureLayerImpl::Create(pending_tree
, 12);
8127 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
8128 FakePictureLayerImpl::Create(pending_tree
, 13);
8129 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
8130 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
8131 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
8132 ASSERT_EQ(raw_replica_mask_layer
,
8133 raw_pending_layer
->replica_layer()->mask_layer());
8135 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8136 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8137 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
8138 pending_tree
->DidBecomeActive();
8139 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
8140 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
8141 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
8144 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
8145 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
8146 host_impl_
->SetViewportSize(gfx::Size(50, 50));
8149 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
8151 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
8152 float page_scale_factor
= 1.f
;
8154 // The scroll deltas should have the page scale factor applied.
8156 host_impl_
->active_tree()->PushPageScaleFromMainThread(
8157 page_scale_factor
, min_page_scale
, max_page_scale
);
8158 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
8159 scroll_layer
->SetScrollDelta(gfx::Vector2d());
8161 float page_scale_delta
= 2.f
;
8162 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
8163 host_impl_
->PinchGestureBegin();
8164 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
8165 host_impl_
->PinchGestureEnd();
8166 host_impl_
->ScrollEnd();
8168 gfx::Vector2dF
scroll_delta(0, 5);
8169 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8170 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
8171 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
8173 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
8174 host_impl_
->ScrollEnd();
8175 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8176 scroll_layer
->CurrentScrollOffset());
8180 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
8182 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8183 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
8186 int num_lost_surfaces_
;
8189 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
8190 // Really we just need at least one client notification each time
8191 // we go from having a valid output surface to not having a valid output
8193 EXPECT_EQ(0, num_lost_surfaces_
);
8194 host_impl_
->DidLoseOutputSurface();
8195 EXPECT_EQ(1, num_lost_surfaces_
);
8196 host_impl_
->DidLoseOutputSurface();
8197 EXPECT_LE(1, num_lost_surfaces_
);
8200 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
8201 LayerTreeHostImpl::FrameData frame
;
8202 frame
.render_passes
.push_back(RenderPass::Create());
8203 RenderPass
* pass3
= frame
.render_passes
.back();
8204 frame
.render_passes
.push_back(RenderPass::Create());
8205 RenderPass
* pass2
= frame
.render_passes
.back();
8206 frame
.render_passes
.push_back(RenderPass::Create());
8207 RenderPass
* pass1
= frame
.render_passes
.back();
8209 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8210 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8211 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8213 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8214 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8215 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8217 // Add a quad to each pass so they aren't empty.
8218 SolidColorDrawQuad
* color_quad
;
8219 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8220 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8221 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8222 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8223 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8224 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8226 // pass3 is referenced by pass2.
8227 RenderPassDrawQuad
* rpdq
=
8228 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8229 rpdq
->material
= DrawQuad::RENDER_PASS
;
8230 rpdq
->render_pass_id
= pass3
->id
;
8232 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
8233 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8234 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8235 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8236 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8237 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8238 EXPECT_EQ(1u, frame
.render_passes
.size());
8239 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8242 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
8243 LayerTreeHostImpl::FrameData frame
;
8244 frame
.render_passes
.push_back(RenderPass::Create());
8245 RenderPass
* pass3
= frame
.render_passes
.back();
8246 frame
.render_passes
.push_back(RenderPass::Create());
8247 RenderPass
* pass2
= frame
.render_passes
.back();
8248 frame
.render_passes
.push_back(RenderPass::Create());
8249 RenderPass
* pass1
= frame
.render_passes
.back();
8251 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8252 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8253 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8255 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8256 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8257 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8259 // pass1 is not empty, but pass2 and pass3 are.
8260 SolidColorDrawQuad
* color_quad
;
8261 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8262 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8264 // pass3 is referenced by pass2.
8265 RenderPassDrawQuad
* rpdq
=
8266 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8267 rpdq
->material
= DrawQuad::RENDER_PASS
;
8268 rpdq
->render_pass_id
= pass3
->id
;
8270 // pass2 is referenced by pass1.
8271 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8272 rpdq
->material
= DrawQuad::RENDER_PASS
;
8273 rpdq
->render_pass_id
= pass2
->id
;
8275 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8276 // should be removed.
8277 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8278 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8279 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8280 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8281 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8282 EXPECT_EQ(1u, frame
.render_passes
.size());
8283 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8284 // The RenderPassDrawQuad should be removed from pass1.
8285 EXPECT_EQ(1u, pass1
->quad_list
.size());
8286 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
8289 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
8290 LayerTreeHostImpl::FrameData frame
;
8291 frame
.render_passes
.push_back(RenderPass::Create());
8292 RenderPass
* pass3
= frame
.render_passes
.back();
8293 frame
.render_passes
.push_back(RenderPass::Create());
8294 RenderPass
* pass2
= frame
.render_passes
.back();
8295 frame
.render_passes
.push_back(RenderPass::Create());
8296 RenderPass
* pass1
= frame
.render_passes
.back();
8298 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8299 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8300 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8302 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8303 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8304 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8306 // pass3 is referenced by pass2.
8307 RenderPassDrawQuad
* rpdq
=
8308 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8309 rpdq
->material
= DrawQuad::RENDER_PASS
;
8310 rpdq
->render_pass_id
= pass3
->id
;
8312 // pass2 is referenced by pass1.
8313 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8314 rpdq
->material
= DrawQuad::RENDER_PASS
;
8315 rpdq
->render_pass_id
= pass2
->id
;
8317 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8318 // should be removed. Then pass1 is empty too, but it's the root so it should
8320 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8321 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8322 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8323 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8324 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8325 EXPECT_EQ(1u, frame
.render_passes
.size());
8326 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8327 // The RenderPassDrawQuad should be removed from pass1.
8328 EXPECT_EQ(0u, pass1
->quad_list
.size());
8331 class FakeVideoFrameController
: public VideoFrameController
{
8333 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
8334 begin_frame_args_
= args
;
8335 did_draw_frame_
= false;
8338 void DidDrawFrame() override
{ did_draw_frame_
= true; }
8340 const BeginFrameArgs
& begin_frame_args() const { return begin_frame_args_
; }
8342 bool did_draw_frame() const { return did_draw_frame_
; }
8345 BeginFrameArgs begin_frame_args_
;
8346 bool did_draw_frame_
= false;
8349 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
8350 BeginFrameArgs begin_frame_args
=
8351 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8352 FakeVideoFrameController controller
;
8354 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8355 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8356 host_impl_
->AddVideoFrameController(&controller
);
8357 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8358 host_impl_
->DidFinishImplFrame();
8360 EXPECT_FALSE(controller
.did_draw_frame());
8361 LayerTreeHostImpl::FrameData frame
;
8362 host_impl_
->DidDrawAllLayers(frame
);
8363 EXPECT_TRUE(controller
.did_draw_frame());
8365 controller
.OnBeginFrame(begin_frame_args
);
8366 EXPECT_FALSE(controller
.did_draw_frame());
8367 host_impl_
->RemoveVideoFrameController(&controller
);
8368 host_impl_
->DidDrawAllLayers(frame
);
8369 EXPECT_FALSE(controller
.did_draw_frame());
8372 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
8373 BeginFrameArgs begin_frame_args
=
8374 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8375 FakeVideoFrameController controller
;
8377 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8378 host_impl_
->DidFinishImplFrame();
8380 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8381 host_impl_
->AddVideoFrameController(&controller
);
8382 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8384 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8385 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8386 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8387 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8389 EXPECT_FALSE(controller
.did_draw_frame());
8390 LayerTreeHostImpl::FrameData frame
;
8391 host_impl_
->DidDrawAllLayers(frame
);
8392 EXPECT_TRUE(controller
.did_draw_frame());
8394 controller
.OnBeginFrame(begin_frame_args
);
8395 EXPECT_FALSE(controller
.did_draw_frame());
8396 host_impl_
->RemoveVideoFrameController(&controller
);
8397 host_impl_
->DidDrawAllLayers(frame
);
8398 EXPECT_FALSE(controller
.did_draw_frame());
8401 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
8402 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8404 host_impl_
->SetHasGpuRasterizationTrigger(true);
8405 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8406 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
8407 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8409 host_impl_
->SetHasGpuRasterizationTrigger(false);
8410 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8411 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
8412 host_impl_
->gpu_rasterization_status());
8413 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8415 host_impl_
->SetHasGpuRasterizationTrigger(true);
8416 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8417 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
8418 host_impl_
->gpu_rasterization_status());
8419 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8420 EXPECT_FALSE(host_impl_
->use_msaa());
8422 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
8423 TestWebGraphicsContext3D::Create();
8424 context_with_msaa
->SetMaxSamples(8);
8426 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
8427 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
8428 EXPECT_TRUE(CreateHostImpl(
8429 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
8430 host_impl_
->SetHasGpuRasterizationTrigger(true);
8431 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8432 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
8433 host_impl_
->gpu_rasterization_status());
8434 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8435 EXPECT_TRUE(host_impl_
->use_msaa());
8437 LayerTreeSettings settings
= DefaultSettings();
8438 settings
.gpu_rasterization_enabled
= false;
8439 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8440 host_impl_
->SetHasGpuRasterizationTrigger(true);
8441 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8442 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
8443 host_impl_
->gpu_rasterization_status());
8444 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8446 settings
.gpu_rasterization_forced
= true;
8447 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8449 host_impl_
->SetHasGpuRasterizationTrigger(false);
8450 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8451 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
8452 host_impl_
->gpu_rasterization_status());
8453 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8456 // A mock output surface which lets us detect calls to ForceReclaimResources.
8457 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
8459 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
8460 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8461 TestContextProvider::Create(), TestContextProvider::Create(), false));
8464 MOCK_METHOD0(ForceReclaimResources
, void());
8467 MockReclaimResourcesOutputSurface(
8468 scoped_refptr
<ContextProvider
> context_provider
,
8469 scoped_refptr
<ContextProvider
> worker_context_provider
,
8470 bool delegated_rendering
)
8471 : FakeOutputSurface(context_provider
,
8472 worker_context_provider
,
8473 delegated_rendering
) {}
8476 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8477 // being reclaimed to block drawing between BeginCommit / Swap. This test
8478 // ensures that BeginCommit triggers ForceReclaimResources. See
8479 // crbug.com/489515.
8480 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
8481 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
8482 MockReclaimResourcesOutputSurface::Create3d());
8483 // Hold an unowned pointer to the output surface to use for mock expectations.
8484 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
8486 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
8487 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
8488 host_impl_
->BeginCommit();