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 output_surface_
= output_surface
.Pass();
172 bool init
= host_impl_
->InitializeRenderer(output_surface_
.get());
173 host_impl_
->SetViewportSize(gfx::Size(10, 10));
174 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
175 // Set the BeginFrameArgs so that methods which use it are able to.
176 host_impl_
->WillBeginImplFrame(CreateBeginFrameArgsForTesting(
177 BEGINFRAME_FROM_HERE
,
178 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1)));
179 host_impl_
->DidFinishImplFrame();
183 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
184 root
->SetPosition(gfx::PointF());
185 root
->SetBounds(gfx::Size(10, 10));
186 root
->SetDrawsContent(true);
187 root
->draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
188 root
->SetHasRenderSurface(true);
189 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
192 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
193 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
194 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
195 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
198 static ::testing::AssertionResult
ScrollInfoContains(
199 const ScrollAndScaleSet
& scroll_info
,
201 const gfx::Vector2d
& scroll_delta
) {
202 int times_encountered
= 0;
204 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
205 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
208 if (scroll_delta
!= scroll_info
.scrolls
[i
].scroll_delta
) {
209 return ::testing::AssertionFailure()
210 << "Expected " << scroll_delta
.ToString() << ", not "
211 << scroll_info
.scrolls
[i
].scroll_delta
.ToString();
216 if (times_encountered
!= 1)
217 return ::testing::AssertionFailure() << "No layer found with id " << id
;
218 return ::testing::AssertionSuccess();
221 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
222 int times_encountered
= 0;
224 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
225 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
230 ASSERT_EQ(0, times_encountered
);
233 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
234 const gfx::Size
& content_size
) {
235 // Create both an inner viewport scroll layer and an outer viewport scroll
236 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
237 // 0x0, so the scrolls will be applied directly to the inner viewport.
238 const int kOuterViewportClipLayerId
= 116;
239 const int kOuterViewportScrollLayerId
= 117;
240 const int kContentLayerId
= 118;
241 const int kInnerViewportScrollLayerId
= 2;
242 const int kInnerViewportClipLayerId
= 4;
243 const int kPageScaleLayerId
= 5;
245 scoped_ptr
<LayerImpl
> root
=
246 LayerImpl::Create(layer_tree_impl
, 1);
247 root
->SetBounds(content_size
);
248 root
->SetPosition(gfx::PointF());
249 root
->SetHasRenderSurface(true);
251 scoped_ptr
<LayerImpl
> inner_scroll
=
252 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
253 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
254 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
256 scoped_ptr
<LayerImpl
> inner_clip
=
257 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
258 inner_clip
->SetBounds(
259 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
261 scoped_ptr
<LayerImpl
> page_scale
=
262 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
264 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
265 inner_scroll
->SetBounds(content_size
);
266 inner_scroll
->SetPosition(gfx::PointF());
268 scoped_ptr
<LayerImpl
> outer_clip
=
269 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
270 outer_clip
->SetBounds(content_size
);
271 outer_clip
->SetIsContainerForFixedPositionLayers(true);
273 scoped_ptr
<LayerImpl
> outer_scroll
=
274 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
275 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
276 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
277 outer_scroll
->SetBounds(content_size
);
278 outer_scroll
->SetPosition(gfx::PointF());
280 scoped_ptr
<LayerImpl
> contents
=
281 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
282 contents
->SetDrawsContent(true);
283 contents
->SetBounds(content_size
);
284 contents
->SetPosition(gfx::PointF());
286 outer_scroll
->AddChild(contents
.Pass());
287 outer_clip
->AddChild(outer_scroll
.Pass());
288 inner_scroll
->AddChild(outer_clip
.Pass());
289 page_scale
->AddChild(inner_scroll
.Pass());
290 inner_clip
->AddChild(page_scale
.Pass());
291 root
->AddChild(inner_clip
.Pass());
293 layer_tree_impl
->SetRootLayer(root
.Pass());
294 layer_tree_impl
->SetViewportLayersFromIds(
295 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
296 kOuterViewportScrollLayerId
);
298 layer_tree_impl
->DidBecomeActive();
299 return layer_tree_impl
->InnerViewportScrollLayer();
302 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
303 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
304 host_impl_
->active_tree(), content_size
);
305 host_impl_
->active_tree()->DidBecomeActive();
309 // Sets up a typical virtual viewport setup with one child content layer.
310 // Returns a pointer to the content layer.
311 LayerImpl
* CreateBasicVirtualViewportLayers(const gfx::Size
& viewport_size
,
312 const gfx::Size
& content_size
) {
313 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
314 // the inner a different size from the outer. We'll reuse its layer
315 // hierarchy but adjust the sizing to our needs.
316 CreateScrollAndContentsLayers(host_impl_
->active_tree(), content_size
);
318 LayerImpl
* content_layer
=
319 host_impl_
->OuterViewportScrollLayer()->children().back();
320 content_layer
->SetBounds(content_size
);
321 host_impl_
->OuterViewportScrollLayer()->SetBounds(content_size
);
323 LayerImpl
* outer_clip
= host_impl_
->OuterViewportScrollLayer()->parent();
324 outer_clip
->SetBounds(viewport_size
);
326 LayerImpl
* inner_clip_layer
=
327 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
328 inner_clip_layer
->SetBounds(viewport_size
);
329 host_impl_
->InnerViewportScrollLayer()->SetBounds(viewport_size
);
331 host_impl_
->SetViewportSize(viewport_size
);
332 host_impl_
->active_tree()->DidBecomeActive();
334 return content_layer
;
337 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
338 const gfx::Size
& size
,
339 LayerImpl
* clip_layer
) {
341 DCHECK(id
!= clip_layer
->id());
342 scoped_ptr
<LayerImpl
> layer
=
343 LayerImpl::Create(host_impl_
->active_tree(), id
);
344 layer
->SetScrollClipLayer(clip_layer
->id());
345 layer
->SetDrawsContent(true);
346 layer
->SetBounds(size
);
347 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
352 LayerTreeHostImpl::FrameData frame
;
353 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
354 host_impl_
->DrawLayers(&frame
);
355 host_impl_
->DidDrawAllLayers(frame
);
358 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
359 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
360 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
361 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
362 float device_scale_factor
);
364 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
365 // Note: It is not possible to disable the renderer once it has been set,
366 // so we do not need to test that disabling the renderer notifies us
367 // that can_draw changed.
368 EXPECT_FALSE(host_impl_
->CanDraw());
369 on_can_draw_state_changed_called_
= false;
371 // Set up the root layer, which allows us to draw.
372 SetupScrollAndContentsLayers(gfx::Size(100, 100));
373 EXPECT_TRUE(host_impl_
->CanDraw());
374 EXPECT_TRUE(on_can_draw_state_changed_called_
);
375 on_can_draw_state_changed_called_
= false;
377 // Toggle the root layer to make sure it toggles can_draw
378 host_impl_
->active_tree()->SetRootLayer(nullptr);
379 EXPECT_FALSE(host_impl_
->CanDraw());
380 EXPECT_TRUE(on_can_draw_state_changed_called_
);
381 on_can_draw_state_changed_called_
= false;
383 SetupScrollAndContentsLayers(gfx::Size(100, 100));
384 EXPECT_TRUE(host_impl_
->CanDraw());
385 EXPECT_TRUE(on_can_draw_state_changed_called_
);
386 on_can_draw_state_changed_called_
= false;
388 // Toggle the device viewport size to make sure it toggles can_draw.
389 host_impl_
->SetViewportSize(gfx::Size());
391 EXPECT_TRUE(host_impl_
->CanDraw());
393 EXPECT_FALSE(host_impl_
->CanDraw());
395 EXPECT_TRUE(on_can_draw_state_changed_called_
);
396 on_can_draw_state_changed_called_
= false;
398 host_impl_
->SetViewportSize(gfx::Size(100, 100));
399 EXPECT_TRUE(host_impl_
->CanDraw());
400 EXPECT_TRUE(on_can_draw_state_changed_called_
);
401 on_can_draw_state_changed_called_
= false;
404 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
407 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
408 return FakeOutputSurface::Create3d();
411 void DrawOneFrame() {
412 LayerTreeHostImpl::FrameData frame_data
;
413 host_impl_
->PrepareToDraw(&frame_data
);
414 host_impl_
->DidDrawAllLayers(frame_data
);
418 DebugScopedSetImplThread always_impl_thread_
;
419 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
421 TestSharedBitmapManager shared_bitmap_manager_
;
422 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
423 TestTaskGraphRunner task_graph_runner_
;
424 scoped_ptr
<OutputSurface
> output_surface_
;
425 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
426 FakeRenderingStatsInstrumentation stats_instrumentation_
;
427 bool on_can_draw_state_changed_called_
;
428 bool did_notify_ready_to_activate_
;
429 bool did_request_commit_
;
430 bool did_request_redraw_
;
431 bool did_request_animate_
;
432 bool did_request_prepare_tiles_
;
433 bool did_complete_page_scale_animation_
;
434 bool reduce_memory_result_
;
435 base::Closure animation_task_
;
436 base::TimeDelta requested_animation_delay_
;
439 // A test fixture for new animation timelines tests.
440 class LayerTreeHostImplTimelinesTest
: public LayerTreeHostImplTest
{
442 void SetUp() override
{
443 LayerTreeSettings settings
= DefaultSettings();
444 settings
.use_compositor_animation_timelines
= true;
445 CreateHostImpl(settings
, CreateOutputSurface());
449 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
450 bool always_draw
= false;
451 CheckNotifyCalledIfCanDrawChanged(always_draw
);
454 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
455 CreateHostImpl(DefaultSettings(),
456 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
458 bool always_draw
= true;
459 CheckNotifyCalledIfCanDrawChanged(always_draw
);
462 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
463 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
465 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
466 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
469 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
471 scoped_ptr
<LayerImpl
> root
=
472 LayerImpl::Create(host_impl_
->active_tree(), 1);
473 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
474 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
475 root
->children()[1]->AddChild(
476 LayerImpl::Create(host_impl_
->active_tree(), 4));
477 root
->children()[1]->AddChild(
478 LayerImpl::Create(host_impl_
->active_tree(), 5));
479 root
->children()[1]->children()[0]->AddChild(
480 LayerImpl::Create(host_impl_
->active_tree(), 6));
481 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
483 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
485 ExpectClearedScrollDeltasRecursive(root
);
487 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
489 scroll_info
= host_impl_
->ProcessScrollDeltas();
490 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
491 ExpectClearedScrollDeltasRecursive(root
);
493 scroll_info
= host_impl_
->ProcessScrollDeltas();
494 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
495 ExpectClearedScrollDeltasRecursive(root
);
498 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
499 gfx::ScrollOffset
scroll_offset(20, 30);
500 gfx::Vector2d
scroll_delta(11, -15);
502 scoped_ptr
<LayerImpl
> root_clip
=
503 LayerImpl::Create(host_impl_
->active_tree(), 2);
504 scoped_ptr
<LayerImpl
> root
=
505 LayerImpl::Create(host_impl_
->active_tree(), 1);
506 root_clip
->SetBounds(gfx::Size(10, 10));
507 LayerImpl
* root_layer
= root
.get();
508 root_clip
->AddChild(root
.Pass());
509 root_layer
->SetBounds(gfx::Size(110, 110));
510 root_layer
->SetScrollClipLayer(root_clip
->id());
511 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
512 root_layer
->ScrollBy(scroll_delta
);
513 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
515 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
517 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
519 scroll_info
= host_impl_
->ProcessScrollDeltas();
520 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
521 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(), scroll_delta
));
523 gfx::Vector2d
scroll_delta2(-5, 27);
524 root
->ScrollBy(scroll_delta2
);
525 scroll_info
= host_impl_
->ProcessScrollDeltas();
526 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
527 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
528 scroll_delta
+ scroll_delta2
));
530 root
->ScrollBy(gfx::Vector2d());
531 scroll_info
= host_impl_
->ProcessScrollDeltas();
532 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
533 scroll_delta
+ scroll_delta2
));
536 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
537 SetupScrollAndContentsLayers(gfx::Size(100, 100));
538 host_impl_
->SetViewportSize(gfx::Size(50, 50));
541 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
542 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
543 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
544 InputHandler::WHEEL
));
545 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
546 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
547 InputHandler::WHEEL
));
548 host_impl_
->ScrollEnd();
549 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
550 InputHandler::WHEEL
));
551 EXPECT_TRUE(did_request_redraw_
);
552 EXPECT_TRUE(did_request_commit_
);
555 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
556 SetupScrollAndContentsLayers(gfx::Size(100, 100));
557 host_impl_
->SetViewportSize(gfx::Size(50, 50));
560 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
561 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
562 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
563 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
564 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
565 host_impl_
->ScrollEnd();
566 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
569 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
570 // We should not crash when trying to scroll an empty layer tree.
571 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
572 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
575 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
576 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
577 TestWebGraphicsContext3D::Create();
578 context_owned
->set_context_lost(true);
580 // Initialization will fail.
581 EXPECT_FALSE(CreateHostImpl(
582 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
584 SetupScrollAndContentsLayers(gfx::Size(100, 100));
586 // We should not crash when trying to scroll after the renderer initialization
588 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
589 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
592 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
593 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
594 host_impl_
->SetViewportSize(gfx::Size(50, 50));
597 // We should not crash if the tree is replaced while we are scrolling.
598 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
599 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
600 host_impl_
->active_tree()->DetachLayerTree();
602 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
604 // We should still be scrolling, because the scrolled layer also exists in the
606 gfx::Vector2d
scroll_delta(0, 10);
607 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
608 host_impl_
->ScrollEnd();
609 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
611 ScrollInfoContains(*scroll_info
, scroll_layer
->id(), scroll_delta
));
614 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
615 SetupScrollAndContentsLayers(gfx::Size(100, 100));
616 host_impl_
->SetViewportSize(gfx::Size(50, 50));
618 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
620 // With registered event handlers, wheel scrolls don't necessarily
621 // have to go to the main thread.
622 root
->SetHaveWheelEventHandlers(true);
623 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
624 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
625 host_impl_
->ScrollEnd();
627 // But typically the scroll-blocks-on mode will require them to.
628 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
629 SCROLL_BLOCKS_ON_START_TOUCH
);
630 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
631 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
633 // But gesture scrolls can still be handled.
634 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
635 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
636 host_impl_
->ScrollEnd();
638 // And if the handlers go away, wheel scrolls can again be processed
639 // on impl (despite the scroll-blocks-on mode).
640 root
->SetHaveWheelEventHandlers(false);
641 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
642 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
643 host_impl_
->ScrollEnd();
646 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
647 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
648 host_impl_
->SetViewportSize(gfx::Size(50, 50));
650 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
652 LayerImpl
* child
= 0;
654 scoped_ptr
<LayerImpl
> child_layer
=
655 LayerImpl::Create(host_impl_
->active_tree(), 6);
656 child
= child_layer
.get();
657 child_layer
->SetDrawsContent(true);
658 child_layer
->SetPosition(gfx::PointF(0, 20));
659 child_layer
->SetBounds(gfx::Size(50, 50));
660 scroll
->AddChild(child_layer
.Pass());
663 // Touch handler regions determine whether touch events block scroll.
664 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
665 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
666 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
667 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
668 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
670 // But they don't influence the actual handling of the scroll gestures.
671 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
672 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
673 host_impl_
->ScrollEnd();
675 // It's the union of scroll-blocks-on mode bits across all layers in the
676 // scroll paret chain that matters.
677 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
678 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
679 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
680 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
681 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
684 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
685 SetupScrollAndContentsLayers(gfx::Size(100, 100));
686 host_impl_
->SetViewportSize(gfx::Size(50, 50));
688 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
690 // With registered scroll handlers, scrolls don't generally have to go
691 // to the main thread.
692 root
->SetHaveScrollEventHandlers(true);
693 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
694 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
695 host_impl_
->ScrollEnd();
697 // Even the default scroll blocks on mode doesn't require this.
698 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
699 SCROLL_BLOCKS_ON_START_TOUCH
);
700 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
701 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
702 host_impl_
->ScrollEnd();
704 // But the page can opt in to blocking on scroll event handlers.
705 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
706 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
707 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
709 // GESTURE and WHEEL scrolls behave identically in this regard.
710 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
711 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
713 // And if the handlers go away, scrolls can again be processed on impl
714 // (despite the scroll-blocks-on mode).
715 root
->SetHaveScrollEventHandlers(false);
716 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
717 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
718 host_impl_
->ScrollEnd();
721 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
722 host_impl_
->SetViewportSize(gfx::Size(50, 50));
724 // Create a normal scrollable root layer
725 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
726 LayerImpl
* root_child
= root_scroll
->children()[0];
727 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
730 // Create two child scrollable layers
731 LayerImpl
* child1
= 0;
733 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
734 LayerImpl::Create(host_impl_
->active_tree(), 6);
735 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
736 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
737 child1
= scrollable_child_1
.get();
738 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
739 scrollable_child_1
->SetHaveWheelEventHandlers(true);
740 scrollable_child_1
->SetHaveScrollEventHandlers(true);
741 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
742 root_child
->AddChild(scrollable_child_clip_1
.Pass());
745 LayerImpl
* child2
= 0;
747 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
748 LayerImpl::Create(host_impl_
->active_tree(), 8);
749 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
750 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
751 child2
= scrollable_child_2
.get();
752 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
753 scrollable_child_2
->SetHaveWheelEventHandlers(true);
754 scrollable_child_2
->SetHaveScrollEventHandlers(true);
755 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
756 root_child
->AddChild(scrollable_child_clip_2
.Pass());
759 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
760 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
761 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
762 host_impl_
->ScrollEnd();
763 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
764 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
765 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
767 // But not those that hit only other layers.
768 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
769 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
770 host_impl_
->ScrollEnd();
772 // It's the union of bits set across the scroll ancestor chain that matters.
773 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
774 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
775 host_impl_
->ScrollEnd();
776 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
777 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
778 host_impl_
->ScrollEnd();
779 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
780 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
781 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
782 host_impl_
->ScrollEnd();
783 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
784 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
785 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
786 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
787 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
788 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
789 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
792 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
793 SetupScrollAndContentsLayers(gfx::Size(100, 100));
794 host_impl_
->SetViewportSize(gfx::Size(50, 50));
797 // Ignore the fling since no layer is being scrolled
798 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
800 // Start scrolling a layer
801 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
802 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
804 // Now the fling should go ahead since we've started scrolling a layer
805 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
808 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
809 SetupScrollAndContentsLayers(gfx::Size(100, 100));
810 host_impl_
->SetViewportSize(gfx::Size(50, 50));
813 // Ignore the fling since no layer is being scrolled
814 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
816 // Start scrolling a layer
817 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
818 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
820 // Now the fling should go ahead since we've started scrolling a layer
821 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
824 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
825 SetupScrollAndContentsLayers(gfx::Size(100, 100));
826 host_impl_
->SetViewportSize(gfx::Size(50, 50));
828 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
830 root
->SetShouldScrollOnMainThread(true);
832 // Start scrolling a layer
833 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
834 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
836 // The fling should be ignored since there's no layer being scrolled impl-side
837 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
840 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
841 SetupScrollAndContentsLayers(gfx::Size(100, 100));
842 host_impl_
->SetViewportSize(gfx::Size(50, 50));
844 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
846 root
->SetShouldScrollOnMainThread(true);
848 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
849 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
850 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
851 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
854 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
855 SetupScrollAndContentsLayers(gfx::Size(200, 200));
856 host_impl_
->SetViewportSize(gfx::Size(100, 100));
858 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
859 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
863 // All scroll types inside the non-fast scrollable region should fail.
864 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
865 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
866 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
867 InputHandler::WHEEL
));
868 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
869 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
870 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
871 InputHandler::GESTURE
));
873 // All scroll types outside this region should succeed.
874 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
875 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
876 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
877 InputHandler::GESTURE
));
878 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
879 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
880 InputHandler::GESTURE
));
881 host_impl_
->ScrollEnd();
882 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
883 InputHandler::GESTURE
));
884 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
885 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
886 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
887 InputHandler::GESTURE
));
888 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
889 host_impl_
->ScrollEnd();
890 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
891 InputHandler::GESTURE
));
894 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
895 SetupScrollAndContentsLayers(gfx::Size(200, 200));
896 host_impl_
->SetViewportSize(gfx::Size(100, 100));
898 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
899 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
900 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
904 // This point would fall into the non-fast scrollable region except that we've
905 // moved the layer down by 25 pixels.
906 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
907 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
908 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
909 InputHandler::WHEEL
));
910 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
911 host_impl_
->ScrollEnd();
913 // This point is still inside the non-fast region.
914 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
915 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
918 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
919 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
920 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
921 host_impl_
->SetViewportSize(gfx::Size(50, 50));
924 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
925 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
926 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
927 host_impl_
->ScrollEnd();
928 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
931 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
932 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
933 scroll_layer
->SetHaveScrollEventHandlers(true);
934 host_impl_
->SetViewportSize(gfx::Size(50, 50));
937 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
938 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
939 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
940 host_impl_
->ScrollEnd();
941 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
944 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
945 SetupScrollAndContentsLayers(gfx::Size(200, 200));
946 host_impl_
->SetViewportSize(gfx::Size(100, 100));
950 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
951 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
953 // Trying to scroll to the left/top will not succeed.
955 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
957 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
959 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
961 // Scrolling to the right/bottom will succeed.
963 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
965 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
967 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
969 // Scrolling to left/top will now succeed.
971 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
973 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
975 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
977 // Scrolling diagonally against an edge will succeed.
979 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
981 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
983 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
985 // Trying to scroll more than the available space will also succeed.
987 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
990 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
991 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
992 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
996 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
997 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
999 // Trying to scroll without a vertical scrollbar will fail.
1000 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
1001 gfx::Point(), SCROLL_FORWARD
));
1002 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
1003 gfx::Point(), SCROLL_BACKWARD
));
1005 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
1006 PaintedScrollbarLayerImpl::Create(
1007 host_impl_
->active_tree(),
1010 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1011 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1012 vertical_scrollbar
.get());
1014 // Trying to scroll with a vertical scrollbar will succeed.
1015 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1016 gfx::Point(), SCROLL_FORWARD
));
1017 EXPECT_FLOAT_EQ(875.f
,
1018 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1019 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1020 gfx::Point(), SCROLL_BACKWARD
));
1023 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1024 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1025 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1027 gfx::Size
overflow_size(400, 400);
1028 ASSERT_EQ(1u, scroll_layer
->children().size());
1029 LayerImpl
* overflow
= scroll_layer
->children()[0];
1030 overflow
->SetBounds(overflow_size
);
1031 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1032 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1033 overflow
->SetPosition(gfx::PointF());
1036 gfx::Point
scroll_position(10, 10);
1038 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1039 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1040 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1041 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1043 gfx::Vector2dF
scroll_delta(10, 10);
1044 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1045 host_impl_
->ScrollEnd();
1046 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1047 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1049 overflow
->set_user_scrollable_horizontal(false);
1051 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1052 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1053 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1054 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1056 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1057 host_impl_
->ScrollEnd();
1058 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1059 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1061 overflow
->set_user_scrollable_vertical(false);
1063 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1064 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1065 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1066 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1068 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1069 host_impl_
->ScrollEnd();
1070 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1071 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1074 TEST_F(LayerTreeHostImplTest
, AnimationSchedulingPendingTree
) {
1075 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1077 host_impl_
->CreatePendingTree();
1078 host_impl_
->pending_tree()->SetRootLayer(
1079 LayerImpl::Create(host_impl_
->pending_tree(), 1));
1080 LayerImpl
* root
= host_impl_
->pending_tree()->root_layer();
1081 root
->SetBounds(gfx::Size(50, 50));
1082 root
->SetHasRenderSurface(true);
1084 root
->AddChild(LayerImpl::Create(host_impl_
->pending_tree(), 2));
1085 LayerImpl
* child
= root
->children()[0];
1086 child
->SetBounds(gfx::Size(10, 10));
1087 child
->draw_properties().visible_layer_rect
= gfx::Rect(10, 10);
1088 child
->SetDrawsContent(true);
1089 AddAnimatedTransformToLayer(child
, 10.0, 3, 0);
1091 EXPECT_FALSE(did_request_animate_
);
1092 EXPECT_FALSE(did_request_redraw_
);
1093 EXPECT_FALSE(did_request_commit_
);
1095 host_impl_
->Animate();
1097 // An animation exists on the pending layer. Doing Animate() requests another
1099 // In reality, animations without has_set_start_time() == true do not need to
1100 // be continuously ticked on the pending tree, so it should not request
1101 // another animation frame here. But we currently do so blindly if any
1102 // animation exists.
1103 EXPECT_TRUE(did_request_animate_
);
1104 // The pending tree with an animation does not need to draw after animating.
1105 EXPECT_FALSE(did_request_redraw_
);
1106 EXPECT_FALSE(did_request_commit_
);
1108 did_request_animate_
= false;
1109 did_request_redraw_
= false;
1110 did_request_commit_
= false;
1112 host_impl_
->ActivateSyncTree();
1114 // When the animation activates, we should request another animation frame
1115 // to keep the animation moving.
1116 EXPECT_TRUE(did_request_animate_
);
1117 // On activation we don't need to request a redraw for the animation,
1118 // activating will draw on its own when it's ready.
1119 EXPECT_FALSE(did_request_redraw_
);
1120 EXPECT_FALSE(did_request_commit_
);
1123 TEST_F(LayerTreeHostImplTest
, AnimationSchedulingActiveTree
) {
1124 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1126 host_impl_
->active_tree()->SetRootLayer(
1127 LayerImpl::Create(host_impl_
->active_tree(), 1));
1128 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
1129 root
->SetBounds(gfx::Size(50, 50));
1130 root
->SetHasRenderSurface(true);
1132 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
1133 LayerImpl
* child
= root
->children()[0];
1134 child
->SetBounds(gfx::Size(10, 10));
1135 child
->draw_properties().visible_layer_rect
= gfx::Rect(10, 10);
1136 child
->SetDrawsContent(true);
1138 // Add a translate from 6,7 to 8,9.
1139 TransformOperations start
;
1140 start
.AppendTranslate(6.f
, 7.f
, 0.f
);
1141 TransformOperations end
;
1142 end
.AppendTranslate(8.f
, 9.f
, 0.f
);
1143 AddAnimatedTransformToLayer(child
, 4.0, start
, end
);
1145 base::TimeTicks now
= base::TimeTicks::Now();
1146 host_impl_
->WillBeginImplFrame(
1147 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now
));
1149 EXPECT_FALSE(did_request_animate_
);
1150 EXPECT_FALSE(did_request_redraw_
);
1151 EXPECT_FALSE(did_request_commit_
);
1153 host_impl_
->ActivateAnimations();
1154 did_request_animate_
= false;
1155 did_request_redraw_
= false;
1156 did_request_commit_
= false;
1158 host_impl_
->Animate();
1160 // An animation exists on the active layer. Doing Animate() requests another
1161 // frame after the current one.
1162 EXPECT_TRUE(did_request_animate_
);
1163 // TODO(danakj): We also need to draw in the current frame if something
1164 // animated, but this is currently handled by
1165 // SchedulerStateMachine::WillAnimate.
1166 EXPECT_FALSE(did_request_redraw_
);
1167 EXPECT_FALSE(did_request_commit_
);
1170 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1171 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1172 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1175 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1176 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1177 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1179 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1180 float page_scale_factor
= 1.f
;
1182 // The impl-based pinch zoom should adjust the max scroll position.
1184 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1185 page_scale_factor
, min_page_scale
, max_page_scale
);
1186 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
1187 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1189 float page_scale_delta
= 2.f
;
1191 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1192 host_impl_
->PinchGestureBegin();
1193 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1194 host_impl_
->PinchGestureEnd();
1195 host_impl_
->ScrollEnd();
1196 EXPECT_FALSE(did_request_animate_
);
1197 EXPECT_TRUE(did_request_redraw_
);
1198 EXPECT_TRUE(did_request_commit_
);
1199 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1201 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1202 host_impl_
->ProcessScrollDeltas();
1203 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1205 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1206 scroll_layer
->MaxScrollOffset().ToString());
1209 // Scrolling after a pinch gesture should always be in local space. The
1210 // scroll deltas have the page scale factor applied.
1212 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1213 page_scale_factor
, min_page_scale
, max_page_scale
);
1214 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
1215 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1217 float page_scale_delta
= 2.f
;
1218 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1219 host_impl_
->PinchGestureBegin();
1220 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1221 host_impl_
->PinchGestureEnd();
1222 host_impl_
->ScrollEnd();
1224 gfx::Vector2d
scroll_delta(0, 10);
1225 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1226 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1227 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1228 host_impl_
->ScrollEnd();
1230 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1231 host_impl_
->ProcessScrollDeltas();
1232 EXPECT_TRUE(ScrollInfoContains(
1233 *scroll_info
.get(), scroll_layer
->id(),
1234 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
)));
1238 TEST_F(LayerTreeHostImplTest
, ViewportScrollOrder
) {
1239 LayerTreeSettings settings
= DefaultSettings();
1240 CreateHostImpl(settings
,
1241 CreateOutputSurface());
1242 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.25f
, 4.f
);
1244 const gfx::Size
content_size(1000, 1000);
1245 const gfx::Size
viewport_size(500, 500);
1246 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1248 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1249 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1252 gfx::Vector2dF(500, 500),
1253 outer_scroll_layer
->MaxScrollOffset());
1255 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1256 host_impl_
->PinchGestureBegin();
1257 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1258 host_impl_
->PinchGestureEnd();
1259 host_impl_
->ScrollEnd();
1261 // Sanity check - we're zoomed in, starting from the origin.
1263 gfx::Vector2dF(0, 0),
1264 outer_scroll_layer
->CurrentScrollOffset());
1266 gfx::Vector2dF(0, 0),
1267 inner_scroll_layer
->CurrentScrollOffset());
1269 // Scroll down - only the inner viewport should scroll.
1270 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1271 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1272 host_impl_
->ScrollEnd();
1275 gfx::Vector2dF(50, 50),
1276 inner_scroll_layer
->CurrentScrollOffset());
1278 gfx::Vector2dF(0, 0),
1279 outer_scroll_layer
->CurrentScrollOffset());
1281 // Scroll down - outer viewport should start scrolling after the inner is at
1283 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1284 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f
, 1000.f
));
1285 host_impl_
->ScrollEnd();
1288 gfx::Vector2dF(250, 250),
1289 inner_scroll_layer
->CurrentScrollOffset());
1291 gfx::Vector2dF(300, 300),
1292 outer_scroll_layer
->CurrentScrollOffset());
1295 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1296 // as expected. That is, scrolling during a pinch should bubble from the inner
1297 // to the outer viewport.
1298 TEST_F(LayerTreeHostImplTest
, ScrollDuringPinchGesture
) {
1299 LayerTreeSettings settings
= DefaultSettings();
1300 CreateHostImpl(settings
,
1301 CreateOutputSurface());
1302 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1304 const gfx::Size
content_size(1000, 1000);
1305 const gfx::Size
viewport_size(500, 500);
1306 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1308 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1309 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1312 gfx::Vector2dF(500, 500),
1313 outer_scroll_layer
->MaxScrollOffset());
1315 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1316 host_impl_
->PinchGestureBegin();
1318 host_impl_
->PinchGestureUpdate(2, gfx::Point(250, 250));
1320 gfx::Vector2dF(0, 0),
1321 outer_scroll_layer
->CurrentScrollOffset());
1323 gfx::Vector2dF(125, 125),
1324 inner_scroll_layer
->CurrentScrollOffset());
1326 // Needed so that the pinch is accounted for in draw properties.
1329 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f
, 10.f
));
1331 gfx::Vector2dF(0, 0),
1332 outer_scroll_layer
->CurrentScrollOffset());
1334 gfx::Vector2dF(130, 130),
1335 inner_scroll_layer
->CurrentScrollOffset());
1339 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f
, 400.f
));
1341 gfx::Vector2dF(80, 80),
1342 outer_scroll_layer
->CurrentScrollOffset());
1344 gfx::Vector2dF(250, 250),
1345 inner_scroll_layer
->CurrentScrollOffset());
1347 host_impl_
->PinchGestureEnd();
1348 host_impl_
->ScrollEnd();
1351 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1352 // a pinch zoom is anchored within a certain margin of the screen edge, we
1353 // should assume the user means to scroll into the edge of the screen.
1354 TEST_F(LayerTreeHostImplTest
, PinchZoomSnapsToScreenEdge
) {
1355 LayerTreeSettings settings
= DefaultSettings();
1356 CreateHostImpl(settings
,
1357 CreateOutputSurface());
1358 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1360 const gfx::Size
content_size(1000, 1000);
1361 const gfx::Size
viewport_size(500, 500);
1362 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1364 int offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
- 5;
1365 gfx::Point
anchor(viewport_size
.width() - offsetFromEdge
,
1366 viewport_size
.height() - offsetFromEdge
);
1368 // Pinch in within the margins. The scroll should stay exactly locked to the
1369 // bottom and right.
1370 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1371 host_impl_
->PinchGestureBegin();
1372 host_impl_
->PinchGestureUpdate(2, anchor
);
1373 host_impl_
->PinchGestureEnd();
1374 host_impl_
->ScrollEnd();
1377 gfx::Vector2dF(250, 250),
1378 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1381 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1382 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1383 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1385 // Pinch in within the margins. The scroll should stay exactly locked to the
1387 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1388 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1389 host_impl_
->PinchGestureBegin();
1390 host_impl_
->PinchGestureUpdate(2, anchor
);
1391 host_impl_
->PinchGestureEnd();
1392 host_impl_
->ScrollEnd();
1395 gfx::Vector2dF(0, 0),
1396 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1399 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1400 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1401 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1403 // Pinch in just outside the margin. There should be no snapping.
1404 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1405 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1406 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1407 host_impl_
->PinchGestureBegin();
1408 host_impl_
->PinchGestureUpdate(2, anchor
);
1409 host_impl_
->PinchGestureEnd();
1410 host_impl_
->ScrollEnd();
1413 gfx::Vector2dF(50, 50),
1414 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1417 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1418 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1419 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1421 // Pinch in just outside the margin. There should be no snapping.
1422 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1423 anchor
= gfx::Point(viewport_size
.width() - offsetFromEdge
,
1424 viewport_size
.height() - offsetFromEdge
);
1425 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1426 host_impl_
->PinchGestureBegin();
1427 host_impl_
->PinchGestureUpdate(2, anchor
);
1428 host_impl_
->PinchGestureEnd();
1429 host_impl_
->ScrollEnd();
1432 gfx::Vector2dF(200, 200),
1433 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1436 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1437 const gfx::Size
content_size(200, 200);
1438 const gfx::Size
viewport_size(100, 100);
1439 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1441 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1442 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1444 // Zoom into the page by a 2X factor
1445 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1446 float page_scale_factor
= 2.f
;
1447 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1448 page_scale_factor
, min_page_scale
, max_page_scale
);
1449 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
1451 // Scroll by a small amount, there should be no bubbling to the outer
1453 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1454 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1455 host_impl_
->ScrollEnd();
1458 gfx::Vector2dF(5, 10),
1459 inner_scroll_layer
->CurrentScrollOffset());
1462 outer_scroll_layer
->CurrentScrollOffset());
1464 // Scroll by the inner viewport's max scroll extent, the remainder
1465 // should bubble up to the outer viewport.
1466 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1467 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1468 host_impl_
->ScrollEnd();
1471 gfx::Vector2dF(50, 50),
1472 inner_scroll_layer
->CurrentScrollOffset());
1474 gfx::Vector2dF(5, 10),
1475 outer_scroll_layer
->CurrentScrollOffset());
1477 // Scroll by the outer viewport's max scroll extent, it should all go to the
1479 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1480 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(190.f
, 180.f
));
1481 host_impl_
->ScrollEnd();
1484 gfx::Vector2dF(100, 100),
1485 outer_scroll_layer
->CurrentScrollOffset());
1487 gfx::Vector2dF(50, 50),
1488 inner_scroll_layer
->CurrentScrollOffset());
1491 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1492 ui::LatencyInfo latency_info
;
1493 latency_info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0,
1495 scoped_ptr
<SwapPromise
> swap_promise(
1496 new LatencyInfoSwapPromise(latency_info
));
1498 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1499 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1500 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1501 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1502 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1503 host_impl_
->ScrollEnd();
1505 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1506 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1507 EXPECT_EQ(latency_info
.trace_id(), scroll_info
->swap_promises
[0]->TraceId());
1510 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1511 // up to the scroll_parent, rather than the stacking parent.
1512 TEST_F(LayerTreeHostImplTest
, ScrollBubblesToScrollParent
) {
1513 LayerImpl
* viewport_scroll
=
1514 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1515 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1517 // Set up two scrolling children of the root, one of which is a scroll parent
1518 // to the other. Scrolls bubbling from the child should bubble to the parent,
1519 // not the viewport.
1522 LayerImpl
*child_clip
;
1524 scoped_ptr
<LayerImpl
> scroll_parent_clip
=
1525 LayerImpl::Create(host_impl_
->active_tree(), 6);
1526 scoped_ptr
<LayerImpl
> scroll_parent
= CreateScrollableLayer(
1527 7, gfx::Size(10, 10), scroll_parent_clip
.get());
1528 parent
= scroll_parent
.get();
1529 scroll_parent_clip
->AddChild(scroll_parent
.Pass());
1531 viewport_scroll
->AddChild(scroll_parent_clip
.Pass());
1533 scoped_ptr
<LayerImpl
> scroll_child_clip
=
1534 LayerImpl::Create(host_impl_
->active_tree(), 8);
1535 scoped_ptr
<LayerImpl
> scroll_child
= CreateScrollableLayer(
1536 9, gfx::Size(10, 10), scroll_child_clip
.get());
1537 child
= scroll_child
.get();
1538 scroll_child
->SetPosition(gfx::Point(20, 20));
1539 scroll_child_clip
->AddChild(scroll_child
.Pass());
1541 child_clip
= scroll_child_clip
.get();
1542 viewport_scroll
->AddChild(scroll_child_clip
.Pass());
1544 child_clip
->SetScrollParent(parent
);
1549 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1550 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1551 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1552 host_impl_
->ScrollEnd();
1554 // The child should be fully scrolled by the first ScrollBy.
1555 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child
->CurrentScrollOffset());
1557 // The scroll_parent should receive the bubbled up second ScrollBy.
1558 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent
->CurrentScrollOffset());
1560 // The viewport shouldn't have been scrolled at all.
1562 gfx::Vector2dF(0, 0),
1563 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1565 gfx::Vector2dF(0, 0),
1566 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1570 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1571 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1572 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1573 host_impl_
->ScrollEnd();
1575 // The first ScrollBy should scroll the parent to its extent.
1576 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent
->CurrentScrollOffset());
1578 // The viewport should now be next in bubbling order.
1580 gfx::Vector2dF(2, 1),
1581 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1583 gfx::Vector2dF(0, 0),
1584 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1589 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1590 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1591 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1594 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1595 DCHECK(scroll_layer
);
1597 float min_page_scale
= 1.f
;
1598 float max_page_scale
= 4.f
;
1600 // Basic pinch zoom in gesture
1602 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1604 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1606 float page_scale_delta
= 2.f
;
1607 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1608 host_impl_
->PinchGestureBegin();
1609 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1610 host_impl_
->PinchGestureEnd();
1611 host_impl_
->ScrollEnd();
1612 EXPECT_FALSE(did_request_animate_
);
1613 EXPECT_TRUE(did_request_redraw_
);
1614 EXPECT_TRUE(did_request_commit_
);
1616 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1617 host_impl_
->ProcessScrollDeltas();
1618 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1623 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1625 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1626 float page_scale_delta
= 10.f
;
1628 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1629 host_impl_
->PinchGestureBegin();
1630 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1631 host_impl_
->PinchGestureEnd();
1632 host_impl_
->ScrollEnd();
1634 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1635 host_impl_
->ProcessScrollDeltas();
1636 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1639 // Zoom-out clamping
1641 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1643 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1644 scroll_layer
->PullDeltaForMainThread();
1645 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1647 float page_scale_delta
= 0.1f
;
1648 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1649 host_impl_
->PinchGestureBegin();
1650 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1651 host_impl_
->PinchGestureEnd();
1652 host_impl_
->ScrollEnd();
1654 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1655 host_impl_
->ProcessScrollDeltas();
1656 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1658 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1661 // Two-finger panning should not happen based on pinch events only
1663 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1665 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1666 scroll_layer
->PullDeltaForMainThread();
1667 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1669 float page_scale_delta
= 1.f
;
1670 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1671 host_impl_
->PinchGestureBegin();
1672 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1673 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1674 host_impl_
->PinchGestureEnd();
1675 host_impl_
->ScrollEnd();
1677 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1678 host_impl_
->ProcessScrollDeltas();
1679 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1680 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1683 // Two-finger panning should work with interleaved scroll events
1685 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1687 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1688 scroll_layer
->PullDeltaForMainThread();
1689 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1691 float page_scale_delta
= 1.f
;
1692 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1693 host_impl_
->PinchGestureBegin();
1694 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1695 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1696 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1697 host_impl_
->PinchGestureEnd();
1698 host_impl_
->ScrollEnd();
1700 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1701 host_impl_
->ProcessScrollDeltas();
1702 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1703 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1704 gfx::Vector2d(-10, -10)));
1707 // Two-finger panning should work when starting fully zoomed out.
1709 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1710 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1711 scroll_layer
->PullDeltaForMainThread();
1712 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1714 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1715 host_impl_
->PinchGestureBegin();
1716 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1717 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1719 // Needed so layer transform includes page scale.
1722 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1723 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1724 host_impl_
->PinchGestureEnd();
1725 host_impl_
->ScrollEnd();
1727 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1728 host_impl_
->ProcessScrollDeltas();
1729 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1730 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1731 gfx::Vector2d(10, 10)));
1735 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1736 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1737 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1740 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1741 DCHECK(scroll_layer
);
1743 float min_page_scale
= 0.5f
;
1744 float max_page_scale
= 4.f
;
1745 base::TimeTicks start_time
= base::TimeTicks() +
1746 base::TimeDelta::FromSeconds(1);
1747 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1748 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1749 base::TimeTicks end_time
= start_time
+ duration
;
1751 BeginFrameArgs begin_frame_args
=
1752 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1754 // Non-anchor zoom-in
1756 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1758 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1760 did_request_redraw_
= false;
1761 did_request_animate_
= false;
1762 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1763 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1768 host_impl_
->ActivateSyncTree();
1769 EXPECT_FALSE(did_request_redraw_
);
1770 EXPECT_TRUE(did_request_animate_
);
1772 did_request_redraw_
= false;
1773 did_request_animate_
= false;
1774 begin_frame_args
.frame_time
= start_time
;
1775 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1776 host_impl_
->Animate();
1777 EXPECT_TRUE(did_request_redraw_
);
1778 EXPECT_TRUE(did_request_animate_
);
1779 host_impl_
->DidFinishImplFrame();
1781 did_request_redraw_
= false;
1782 did_request_animate_
= false;
1783 begin_frame_args
.frame_time
= halfway_through_animation
;
1784 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1785 host_impl_
->Animate();
1786 EXPECT_TRUE(did_request_redraw_
);
1787 EXPECT_TRUE(did_request_animate_
);
1788 host_impl_
->DidFinishImplFrame();
1790 did_request_redraw_
= false;
1791 did_request_animate_
= false;
1792 did_request_commit_
= false;
1793 begin_frame_args
.frame_time
= end_time
;
1794 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1795 host_impl_
->Animate();
1796 EXPECT_TRUE(did_request_commit_
);
1797 EXPECT_FALSE(did_request_animate_
);
1798 host_impl_
->DidFinishImplFrame();
1800 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1801 host_impl_
->ProcessScrollDeltas();
1802 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1803 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1804 gfx::Vector2d(-50, -50)));
1807 start_time
+= base::TimeDelta::FromSeconds(10);
1808 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1809 end_time
+= base::TimeDelta::FromSeconds(10);
1813 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1815 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1817 did_request_redraw_
= false;
1818 did_request_animate_
= false;
1819 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1820 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1821 gfx::Vector2d(25, 25),
1825 host_impl_
->ActivateSyncTree();
1826 EXPECT_FALSE(did_request_redraw_
);
1827 EXPECT_TRUE(did_request_animate_
);
1829 did_request_redraw_
= false;
1830 did_request_animate_
= false;
1831 begin_frame_args
.frame_time
= start_time
;
1832 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1833 host_impl_
->Animate();
1834 EXPECT_TRUE(did_request_redraw_
);
1835 EXPECT_TRUE(did_request_animate_
);
1836 host_impl_
->DidFinishImplFrame();
1838 did_request_redraw_
= false;
1839 did_request_commit_
= false;
1840 did_request_animate_
= false;
1841 begin_frame_args
.frame_time
= end_time
;
1842 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1843 host_impl_
->Animate();
1844 EXPECT_TRUE(did_request_redraw_
);
1845 EXPECT_FALSE(did_request_animate_
);
1846 EXPECT_TRUE(did_request_commit_
);
1847 host_impl_
->DidFinishImplFrame();
1849 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1850 host_impl_
->ProcessScrollDeltas();
1851 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1852 // Pushed to (0,0) via clamping against contents layer size.
1853 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1854 gfx::Vector2d(-50, -50)));
1858 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1859 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1860 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1863 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1864 DCHECK(scroll_layer
);
1866 float min_page_scale
= 0.5f
;
1867 float max_page_scale
= 4.f
;
1868 base::TimeTicks start_time
= base::TimeTicks() +
1869 base::TimeDelta::FromSeconds(1);
1870 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1871 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1872 base::TimeTicks end_time
= start_time
+ duration
;
1874 BeginFrameArgs begin_frame_args
=
1875 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1877 // Anchor zoom with unchanged page scale should not change scroll or scale.
1879 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1881 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1883 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1884 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1889 host_impl_
->ActivateSyncTree();
1890 begin_frame_args
.frame_time
= start_time
;
1891 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1892 host_impl_
->Animate();
1893 host_impl_
->DidFinishImplFrame();
1895 begin_frame_args
.frame_time
= halfway_through_animation
;
1896 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1897 host_impl_
->Animate();
1898 EXPECT_TRUE(did_request_redraw_
);
1899 host_impl_
->DidFinishImplFrame();
1901 begin_frame_args
.frame_time
= end_time
;
1902 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1903 host_impl_
->Animate();
1904 EXPECT_TRUE(did_request_commit_
);
1905 host_impl_
->DidFinishImplFrame();
1907 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1908 host_impl_
->ProcessScrollDeltas();
1909 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1910 ExpectNone(*scroll_info
, scroll_layer
->id());
1914 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1915 host_impl_
->CreatePendingTree();
1916 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
1917 CreateScrollAndContentsLayers(
1918 host_impl_
->pending_tree(),
1919 gfx::Size(100, 100));
1920 host_impl_
->ActivateSyncTree();
1923 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1924 DCHECK(scroll_layer
);
1926 float min_page_scale
= 0.5f
;
1927 float max_page_scale
= 4.f
;
1928 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1930 host_impl_
->ActivateSyncTree();
1932 base::TimeTicks start_time
= base::TimeTicks() +
1933 base::TimeDelta::FromSeconds(1);
1934 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1935 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1936 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1937 base::TimeTicks end_time
= start_time
+ duration
;
1938 float target_scale
= 2.f
;
1940 BeginFrameArgs begin_frame_args
=
1941 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1943 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1945 // Make sure TakePageScaleAnimation works properly.
1947 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1948 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1953 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1954 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1955 EXPECT_EQ(target_scale
, psa
->scale
);
1956 EXPECT_EQ(duration
, psa
->duration
);
1957 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1959 // Recreate the PSA. Nothing should happen here since the tree containing the
1960 // PSA hasn't been activated yet.
1961 did_request_redraw_
= false;
1962 did_request_animate_
= false;
1963 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1964 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1969 begin_frame_args
.frame_time
= halfway_through_animation
;
1970 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1971 host_impl_
->Animate();
1972 EXPECT_FALSE(did_request_animate_
);
1973 EXPECT_FALSE(did_request_redraw_
);
1974 host_impl_
->DidFinishImplFrame();
1976 // Activate the sync tree. This should cause the animation to become enabled.
1977 // It should also clear the pointer on the sync tree.
1978 host_impl_
->ActivateSyncTree();
1980 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1981 EXPECT_FALSE(did_request_redraw_
);
1982 EXPECT_TRUE(did_request_animate_
);
1984 start_time
+= base::TimeDelta::FromSeconds(10);
1985 third_through_animation
+= base::TimeDelta::FromSeconds(10);
1986 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1987 end_time
+= base::TimeDelta::FromSeconds(10);
1989 // From here on, make sure the animation runs as normal.
1990 did_request_redraw_
= false;
1991 did_request_animate_
= false;
1992 begin_frame_args
.frame_time
= start_time
;
1993 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1994 host_impl_
->Animate();
1995 EXPECT_TRUE(did_request_redraw_
);
1996 EXPECT_TRUE(did_request_animate_
);
1997 host_impl_
->DidFinishImplFrame();
1999 did_request_redraw_
= false;
2000 did_request_animate_
= false;
2001 begin_frame_args
.frame_time
= third_through_animation
;
2002 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2003 host_impl_
->Animate();
2004 EXPECT_TRUE(did_request_redraw_
);
2005 EXPECT_TRUE(did_request_animate_
);
2006 host_impl_
->DidFinishImplFrame();
2008 // Another activation shouldn't have any effect on the animation.
2009 host_impl_
->ActivateSyncTree();
2011 did_request_redraw_
= false;
2012 did_request_animate_
= false;
2013 begin_frame_args
.frame_time
= halfway_through_animation
;
2014 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2015 host_impl_
->Animate();
2016 EXPECT_TRUE(did_request_redraw_
);
2017 EXPECT_TRUE(did_request_animate_
);
2018 host_impl_
->DidFinishImplFrame();
2020 did_request_redraw_
= false;
2021 did_request_animate_
= false;
2022 did_request_commit_
= false;
2023 begin_frame_args
.frame_time
= end_time
;
2024 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2025 host_impl_
->Animate();
2026 EXPECT_TRUE(did_request_commit_
);
2027 EXPECT_FALSE(did_request_animate_
);
2028 host_impl_
->DidFinishImplFrame();
2030 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
2031 host_impl_
->ProcessScrollDeltas();
2032 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
2033 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
2034 gfx::Vector2d(-50, -50)));
2037 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
2038 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2039 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2042 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
2043 DCHECK(scroll_layer
);
2045 base::TimeTicks start_time
=
2046 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
2047 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
2048 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
2049 base::TimeTicks end_time
= start_time
+ duration
;
2051 BeginFrameArgs begin_frame_args
=
2052 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
2054 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2055 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
2057 did_complete_page_scale_animation_
= false;
2058 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
2059 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
2060 gfx::Vector2d(), false, 2.f
, duration
)));
2061 host_impl_
->ActivateSyncTree();
2062 begin_frame_args
.frame_time
= start_time
;
2063 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2064 host_impl_
->Animate();
2065 EXPECT_FALSE(did_complete_page_scale_animation_
);
2066 host_impl_
->DidFinishImplFrame();
2068 begin_frame_args
.frame_time
= halfway_through_animation
;
2069 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2070 host_impl_
->Animate();
2071 EXPECT_FALSE(did_complete_page_scale_animation_
);
2072 host_impl_
->DidFinishImplFrame();
2074 begin_frame_args
.frame_time
= end_time
;
2075 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2076 host_impl_
->Animate();
2077 EXPECT_TRUE(did_complete_page_scale_animation_
);
2078 host_impl_
->DidFinishImplFrame();
2081 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
2083 LayerTreeHostImplOverridePhysicalTime(
2084 const LayerTreeSettings
& settings
,
2085 LayerTreeHostImplClient
* client
,
2087 SharedBitmapManager
* manager
,
2088 TaskGraphRunner
* task_graph_runner
,
2089 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
2090 : LayerTreeHostImpl(settings
,
2093 rendering_stats_instrumentation
,
2099 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
2100 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
2101 fake_current_physical_time_
);
2104 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
2105 fake_current_physical_time_
= fake_now
;
2109 base::TimeTicks fake_current_physical_time_
;
2112 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
2114 void SetupLayers(LayerTreeSettings settings
) {
2115 gfx::Size
content_size(100, 100);
2117 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
2118 new LayerTreeHostImplOverridePhysicalTime(
2119 settings
, this, &proxy_
, &shared_bitmap_manager_
,
2120 &task_graph_runner_
, &stats_instrumentation_
);
2121 host_impl_
= make_scoped_ptr(host_impl_override_time
);
2122 output_surface_
= CreateOutputSurface();
2123 host_impl_
->InitializeRenderer(output_surface_
.get());
2125 SetupScrollAndContentsLayers(content_size
);
2126 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2127 host_impl_
->SetViewportSize(
2128 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
2130 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
2131 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 400,
2132 VERTICAL
, 10, 0, false, true);
2133 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
2135 LayerImpl
* scroll
= host_impl_
->InnerViewportScrollLayer();
2136 LayerImpl
* root
= scroll
->parent()->parent();
2137 scrollbar
->SetScrollLayerAndClipLayerByIds(scroll
->id(), root
->id());
2138 root
->AddChild(scrollbar
.Pass());
2140 host_impl_
->active_tree()->DidBecomeActive();
2144 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
2145 LayerTreeSettings settings
;
2146 settings
.scrollbar_animator
= animator
;
2147 settings
.scrollbar_fade_delay_ms
= 20;
2148 settings
.scrollbar_fade_duration_ms
= 20;
2150 SetupLayers(settings
);
2152 base::TimeTicks fake_now
= base::TimeTicks::Now();
2154 EXPECT_FALSE(did_request_animate_
);
2155 EXPECT_FALSE(did_request_redraw_
);
2156 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2157 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2159 // If no scroll happened during a scroll gesture, it should have no effect.
2160 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2161 host_impl_
->ScrollEnd();
2162 EXPECT_FALSE(did_request_animate_
);
2163 EXPECT_FALSE(did_request_redraw_
);
2164 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2165 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2167 // After a scroll, a scrollbar animation should be scheduled about 20ms from
2169 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2170 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2171 EXPECT_FALSE(did_request_animate_
);
2172 EXPECT_TRUE(did_request_redraw_
);
2173 did_request_redraw_
= false;
2174 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2175 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2177 host_impl_
->ScrollEnd();
2178 EXPECT_FALSE(did_request_animate_
);
2179 EXPECT_FALSE(did_request_redraw_
);
2180 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2181 requested_animation_delay_
);
2182 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2184 fake_now
+= requested_animation_delay_
;
2185 requested_animation_delay_
= base::TimeDelta();
2186 animation_task_
.Run();
2187 animation_task_
= base::Closure();
2188 EXPECT_TRUE(did_request_animate_
);
2189 did_request_animate_
= false;
2190 EXPECT_FALSE(did_request_redraw_
);
2192 // After the scrollbar animation begins, we should start getting redraws.
2193 BeginFrameArgs begin_frame_args
=
2194 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, fake_now
);
2195 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2196 host_impl_
->Animate();
2197 EXPECT_TRUE(did_request_animate_
);
2198 did_request_animate_
= false;
2199 EXPECT_TRUE(did_request_redraw_
);
2200 did_request_redraw_
= false;
2201 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2202 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2203 host_impl_
->DidFinishImplFrame();
2205 // Setting the scroll offset outside a scroll should also cause the
2206 // scrollbar to appear and to schedule a scrollbar animation.
2207 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2208 gfx::ScrollOffset(5, 5));
2209 EXPECT_FALSE(did_request_animate_
);
2210 EXPECT_FALSE(did_request_redraw_
);
2211 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2212 requested_animation_delay_
);
2213 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2214 requested_animation_delay_
= base::TimeDelta();
2215 animation_task_
= base::Closure();
2217 // Scrollbar animation is not triggered unnecessarily.
2218 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2219 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2220 EXPECT_FALSE(did_request_animate_
);
2221 EXPECT_TRUE(did_request_redraw_
);
2222 did_request_redraw_
= false;
2223 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2224 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2226 host_impl_
->ScrollEnd();
2227 EXPECT_FALSE(did_request_animate_
);
2228 EXPECT_FALSE(did_request_redraw_
);
2229 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2230 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2232 // Changing page scale triggers scrollbar animation.
2233 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2234 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.1f
);
2235 EXPECT_FALSE(did_request_animate_
);
2236 EXPECT_FALSE(did_request_redraw_
);
2237 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2238 requested_animation_delay_
);
2239 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2240 requested_animation_delay_
= base::TimeDelta();
2241 animation_task_
= base::Closure();
2245 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
2246 RunTest(LayerTreeSettings::LINEAR_FADE
);
2249 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
2250 RunTest(LayerTreeSettings::THINNING
);
2253 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2254 float device_scale_factor
) {
2255 LayerTreeSettings settings
;
2256 settings
.scrollbar_fade_delay_ms
= 500;
2257 settings
.scrollbar_fade_duration_ms
= 300;
2258 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
2260 gfx::Size
viewport_size(300, 200);
2261 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
2262 gfx::ScaleSize(viewport_size
, device_scale_factor
));
2263 gfx::Size
content_size(1000, 1000);
2265 CreateHostImpl(settings
, CreateOutputSurface());
2266 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
2267 host_impl_
->SetViewportSize(device_viewport_size
);
2269 scoped_ptr
<LayerImpl
> root
=
2270 LayerImpl::Create(host_impl_
->active_tree(), 1);
2271 root
->SetBounds(viewport_size
);
2272 root
->SetHasRenderSurface(true);
2274 scoped_ptr
<LayerImpl
> scroll
=
2275 LayerImpl::Create(host_impl_
->active_tree(), 2);
2276 scroll
->SetScrollClipLayer(root
->id());
2277 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2278 scroll
->SetBounds(content_size
);
2279 scroll
->SetIsContainerForFixedPositionLayers(true);
2281 scoped_ptr
<LayerImpl
> contents
=
2282 LayerImpl::Create(host_impl_
->active_tree(), 3);
2283 contents
->SetDrawsContent(true);
2284 contents
->SetBounds(content_size
);
2286 // The scrollbar is on the right side.
2287 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
2288 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
2289 scrollbar
->SetDrawsContent(true);
2290 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
2291 scrollbar
->SetPosition(gfx::Point(285, 0));
2293 scroll
->AddChild(contents
.Pass());
2294 root
->AddChild(scroll
.Pass());
2295 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
2296 root
->AddChild(scrollbar
.Pass());
2298 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2299 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
2301 host_impl_
->active_tree()->DidBecomeActive();
2304 LayerImpl
* root_scroll
=
2305 host_impl_
->active_tree()->InnerViewportScrollLayer();
2306 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
2307 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
2308 static_cast<ScrollbarAnimationControllerThinning
*>(
2309 root_scroll
->scrollbar_animation_controller());
2310 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
2312 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
2313 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2315 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
2316 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2318 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2319 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2321 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
2322 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2323 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2325 did_request_redraw_
= false;
2326 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2327 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
2328 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2329 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
2330 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2331 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
2332 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2335 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
2336 SetupMouseMoveAtWithDeviceScale(1.f
);
2339 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
2340 SetupMouseMoveAtWithDeviceScale(2.f
);
2343 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
2344 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2345 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2346 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2349 CompositorFrameMetadata metadata
=
2350 host_impl_
->MakeCompositorFrameMetadata();
2351 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
2352 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
2353 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
2354 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2355 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2356 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2357 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2358 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2361 // Scrolling should update metadata immediately.
2362 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2363 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2364 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2366 CompositorFrameMetadata metadata
=
2367 host_impl_
->MakeCompositorFrameMetadata();
2368 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2370 host_impl_
->ScrollEnd();
2372 CompositorFrameMetadata metadata
=
2373 host_impl_
->MakeCompositorFrameMetadata();
2374 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2377 // Root "overflow: hidden" properties should be reflected on the outer
2378 // viewport scroll layer.
2380 host_impl_
->active_tree()
2381 ->OuterViewportScrollLayer()
2382 ->set_user_scrollable_horizontal(false);
2383 CompositorFrameMetadata metadata
=
2384 host_impl_
->MakeCompositorFrameMetadata();
2385 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2386 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2388 host_impl_
->active_tree()
2389 ->OuterViewportScrollLayer()
2390 ->set_user_scrollable_vertical(false);
2391 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2392 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2393 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2396 // Re-enable scrollability and verify that overflows are no longer hidden.
2398 host_impl_
->active_tree()
2399 ->OuterViewportScrollLayer()
2400 ->set_user_scrollable_horizontal(true);
2401 host_impl_
->active_tree()
2402 ->OuterViewportScrollLayer()
2403 ->set_user_scrollable_vertical(true);
2404 CompositorFrameMetadata metadata
=
2405 host_impl_
->MakeCompositorFrameMetadata();
2406 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2407 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2410 // Root "overflow: hidden" properties should also be reflected on the
2411 // inner viewport scroll layer.
2413 host_impl_
->active_tree()
2414 ->InnerViewportScrollLayer()
2415 ->set_user_scrollable_horizontal(false);
2416 CompositorFrameMetadata metadata
=
2417 host_impl_
->MakeCompositorFrameMetadata();
2418 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2419 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2421 host_impl_
->active_tree()
2422 ->InnerViewportScrollLayer()
2423 ->set_user_scrollable_vertical(false);
2424 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2425 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2426 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2429 // Page scale should update metadata correctly (shrinking only the viewport).
2430 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
2431 host_impl_
->PinchGestureBegin();
2432 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
2433 host_impl_
->PinchGestureEnd();
2434 host_impl_
->ScrollEnd();
2436 CompositorFrameMetadata metadata
=
2437 host_impl_
->MakeCompositorFrameMetadata();
2438 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2439 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
2440 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
2441 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2442 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2443 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2446 // Likewise if set from the main thread.
2447 host_impl_
->ProcessScrollDeltas();
2448 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
2449 host_impl_
->active_tree()->SetPageScaleOnActiveTree(4.f
);
2451 CompositorFrameMetadata metadata
=
2452 host_impl_
->MakeCompositorFrameMetadata();
2453 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2454 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
2455 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
2456 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2457 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2458 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2462 class DidDrawCheckLayer
: public LayerImpl
{
2464 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2465 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2468 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2469 will_draw_called_
= true;
2470 if (will_draw_returns_false_
)
2472 return LayerImpl::WillDraw(draw_mode
, provider
);
2475 void AppendQuads(RenderPass
* render_pass
,
2476 AppendQuadsData
* append_quads_data
) override
{
2477 append_quads_called_
= true;
2478 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2481 void DidDraw(ResourceProvider
* provider
) override
{
2482 did_draw_called_
= true;
2483 LayerImpl::DidDraw(provider
);
2486 bool will_draw_called() const { return will_draw_called_
; }
2487 bool append_quads_called() const { return append_quads_called_
; }
2488 bool did_draw_called() const { return did_draw_called_
; }
2490 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2492 void ClearDidDrawCheck() {
2493 will_draw_called_
= false;
2494 append_quads_called_
= false;
2495 did_draw_called_
= false;
2498 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2500 void AddCopyRequest() {
2501 ScopedPtrVector
<CopyOutputRequest
> requests
;
2503 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2504 SetHasRenderSurface(true);
2505 PassCopyRequests(&requests
);
2509 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2510 : LayerImpl(tree_impl
, id
),
2511 will_draw_returns_false_(false),
2512 will_draw_called_(false),
2513 append_quads_called_(false),
2514 did_draw_called_(false) {
2515 SetBounds(gfx::Size(10, 10));
2516 SetDrawsContent(true);
2517 draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
2521 bool will_draw_returns_false_
;
2522 bool will_draw_called_
;
2523 bool append_quads_called_
;
2524 bool did_draw_called_
;
2527 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2528 // The root layer is always drawn, so run this test on a child layer that
2529 // will be masked out by the root layer's bounds.
2530 host_impl_
->active_tree()->SetRootLayer(
2531 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2532 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2533 host_impl_
->active_tree()->root_layer());
2535 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2536 root
->SetHasRenderSurface(true);
2537 DidDrawCheckLayer
* layer
=
2538 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2541 LayerTreeHostImpl::FrameData frame
;
2542 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2543 host_impl_
->DrawLayers(&frame
);
2544 host_impl_
->DidDrawAllLayers(frame
);
2546 EXPECT_TRUE(layer
->will_draw_called());
2547 EXPECT_TRUE(layer
->append_quads_called());
2548 EXPECT_TRUE(layer
->did_draw_called());
2551 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2554 LayerTreeHostImpl::FrameData frame
;
2556 layer
->set_will_draw_returns_false();
2557 layer
->ClearDidDrawCheck();
2559 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2560 host_impl_
->DrawLayers(&frame
);
2561 host_impl_
->DidDrawAllLayers(frame
);
2563 EXPECT_TRUE(layer
->will_draw_called());
2564 EXPECT_FALSE(layer
->append_quads_called());
2565 EXPECT_FALSE(layer
->did_draw_called());
2569 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2570 // The root layer is always drawn, so run this test on a child layer that
2571 // will be masked out by the root layer's bounds.
2572 host_impl_
->active_tree()->SetRootLayer(
2573 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2574 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2575 host_impl_
->active_tree()->root_layer());
2576 root
->SetMasksToBounds(true);
2577 root
->SetHasRenderSurface(true);
2578 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2579 DidDrawCheckLayer
* layer
=
2580 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2581 // Ensure visible_layer_rect for layer is empty.
2582 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2583 layer
->SetBounds(gfx::Size(10, 10));
2585 LayerTreeHostImpl::FrameData frame
;
2587 EXPECT_FALSE(layer
->will_draw_called());
2588 EXPECT_FALSE(layer
->did_draw_called());
2590 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
2591 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2592 host_impl_
->DrawLayers(&frame
);
2593 host_impl_
->DidDrawAllLayers(frame
);
2595 EXPECT_FALSE(layer
->will_draw_called());
2596 EXPECT_FALSE(layer
->did_draw_called());
2598 EXPECT_TRUE(layer
->visible_layer_rect().IsEmpty());
2600 // Ensure visible_layer_rect for layer is not empty
2601 layer
->SetPosition(gfx::PointF());
2603 EXPECT_FALSE(layer
->will_draw_called());
2604 EXPECT_FALSE(layer
->did_draw_called());
2606 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2607 host_impl_
->DrawLayers(&frame
);
2608 host_impl_
->DidDrawAllLayers(frame
);
2610 EXPECT_TRUE(layer
->will_draw_called());
2611 EXPECT_TRUE(layer
->did_draw_called());
2613 EXPECT_FALSE(layer
->visible_layer_rect().IsEmpty());
2616 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2617 gfx::Size
big_size(1000, 1000);
2618 host_impl_
->SetViewportSize(big_size
);
2620 host_impl_
->active_tree()->SetRootLayer(
2621 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2622 DidDrawCheckLayer
* root
=
2623 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2625 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2626 DidDrawCheckLayer
* occluded_layer
=
2627 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2629 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2630 root
->SetHasRenderSurface(true);
2631 DidDrawCheckLayer
* top_layer
=
2632 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2633 // This layer covers the occluded_layer above. Make this layer large so it can
2635 top_layer
->SetBounds(big_size
);
2636 top_layer
->SetContentsOpaque(true);
2638 LayerTreeHostImpl::FrameData frame
;
2640 EXPECT_FALSE(occluded_layer
->will_draw_called());
2641 EXPECT_FALSE(occluded_layer
->did_draw_called());
2642 EXPECT_FALSE(top_layer
->will_draw_called());
2643 EXPECT_FALSE(top_layer
->did_draw_called());
2645 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2646 host_impl_
->DrawLayers(&frame
);
2647 host_impl_
->DidDrawAllLayers(frame
);
2649 EXPECT_FALSE(occluded_layer
->will_draw_called());
2650 EXPECT_FALSE(occluded_layer
->did_draw_called());
2651 EXPECT_TRUE(top_layer
->will_draw_called());
2652 EXPECT_TRUE(top_layer
->did_draw_called());
2655 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2656 host_impl_
->active_tree()->SetRootLayer(
2657 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2658 DidDrawCheckLayer
* root
=
2659 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2661 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2662 root
->SetHasRenderSurface(true);
2663 DidDrawCheckLayer
* layer1
=
2664 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2666 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2667 DidDrawCheckLayer
* layer2
=
2668 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2670 layer1
->SetHasRenderSurface(true);
2671 layer1
->SetShouldFlattenTransform(true);
2673 EXPECT_FALSE(root
->did_draw_called());
2674 EXPECT_FALSE(layer1
->did_draw_called());
2675 EXPECT_FALSE(layer2
->did_draw_called());
2677 LayerTreeHostImpl::FrameData frame
;
2678 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2679 host_impl_
->active_tree()->root_layer());
2680 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2681 host_impl_
->DrawLayers(&frame
);
2682 host_impl_
->DidDrawAllLayers(frame
);
2684 EXPECT_TRUE(root
->did_draw_called());
2685 EXPECT_TRUE(layer1
->did_draw_called());
2686 EXPECT_TRUE(layer2
->did_draw_called());
2688 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2689 EXPECT_TRUE(layer1
->render_surface());
2692 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2694 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2697 bool had_incomplete_tile
,
2699 ResourceProvider
* resource_provider
) {
2700 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2703 had_incomplete_tile
,
2705 resource_provider
));
2708 void AppendQuads(RenderPass
* render_pass
,
2709 AppendQuadsData
* append_quads_data
) override
{
2710 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2711 if (had_incomplete_tile_
)
2712 append_quads_data
->num_incomplete_tiles
++;
2714 append_quads_data
->num_missing_tiles
++;
2718 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2721 bool had_incomplete_tile
,
2723 ResourceProvider
* resource_provider
)
2724 : DidDrawCheckLayer(tree_impl
, id
),
2725 tile_missing_(tile_missing
),
2726 had_incomplete_tile_(had_incomplete_tile
) {
2728 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2732 bool had_incomplete_tile_
;
2735 struct PrepareToDrawSuccessTestCase
{
2737 bool has_missing_tile
= false;
2738 bool has_incomplete_tile
= false;
2739 bool is_animating
= false;
2740 bool has_copy_request
= false;
2742 bool high_res_required
= false;
2744 State layer_between
;
2746 DrawResult expected_result
;
2748 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2749 : expected_result(result
) {}
2752 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2753 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2756 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2757 // 1. Animated layer first.
2758 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2759 cases
.back().layer_before
.is_animating
= true;
2760 // 2. Animated layer between.
2761 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2762 cases
.back().layer_between
.is_animating
= true;
2763 // 3. Animated layer last.
2764 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2765 cases
.back().layer_after
.is_animating
= true;
2766 // 4. Missing tile first.
2767 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2768 cases
.back().layer_before
.has_missing_tile
= true;
2769 // 5. Missing tile between.
2770 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2771 cases
.back().layer_between
.has_missing_tile
= true;
2772 // 6. Missing tile last.
2773 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2774 cases
.back().layer_after
.has_missing_tile
= true;
2775 // 7. Incomplete tile first.
2776 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2777 cases
.back().layer_before
.has_incomplete_tile
= true;
2778 // 8. Incomplete tile between.
2779 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2780 cases
.back().layer_between
.has_incomplete_tile
= true;
2781 // 9. Incomplete tile last.
2782 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2783 cases
.back().layer_after
.has_incomplete_tile
= true;
2784 // 10. Animation with missing tile.
2786 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2787 cases
.back().layer_between
.has_missing_tile
= true;
2788 cases
.back().layer_between
.is_animating
= true;
2789 // 11. Animation with incomplete tile.
2790 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2791 cases
.back().layer_between
.has_incomplete_tile
= true;
2792 cases
.back().layer_between
.is_animating
= true;
2794 // 12. High res required.
2795 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2796 cases
.back().high_res_required
= true;
2797 // 13. High res required with incomplete tile.
2799 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2800 cases
.back().high_res_required
= true;
2801 cases
.back().layer_between
.has_incomplete_tile
= true;
2802 // 14. High res required with missing tile.
2804 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2805 cases
.back().high_res_required
= true;
2806 cases
.back().layer_between
.has_missing_tile
= true;
2808 // 15. High res required is higher priority than animating missing tiles.
2810 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2811 cases
.back().high_res_required
= true;
2812 cases
.back().layer_between
.has_missing_tile
= true;
2813 cases
.back().layer_after
.has_missing_tile
= true;
2814 cases
.back().layer_after
.is_animating
= true;
2815 // 16. High res required is higher priority than animating missing tiles.
2817 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2818 cases
.back().high_res_required
= true;
2819 cases
.back().layer_between
.has_missing_tile
= true;
2820 cases
.back().layer_before
.has_missing_tile
= true;
2821 cases
.back().layer_before
.is_animating
= true;
2823 host_impl_
->active_tree()->SetRootLayer(
2824 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2825 DidDrawCheckLayer
* root
=
2826 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2827 root
->SetHasRenderSurface(true);
2829 LayerTreeHostImpl::FrameData frame
;
2830 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2831 host_impl_
->DrawLayers(&frame
);
2832 host_impl_
->DidDrawAllLayers(frame
);
2833 host_impl_
->SwapBuffers(frame
);
2835 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2836 const auto& testcase
= cases
[i
];
2837 std::vector
<LayerImpl
*> to_remove
;
2838 for (auto* child
: root
->children())
2839 to_remove
.push_back(child
);
2840 for (auto* child
: to_remove
)
2841 root
->RemoveChild(child
);
2843 std::ostringstream scope
;
2844 scope
<< "Test case: " << i
;
2845 SCOPED_TRACE(scope
.str());
2847 root
->AddChild(MissingTextureAnimatingLayer::Create(
2848 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2849 testcase
.layer_before
.has_incomplete_tile
,
2850 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2851 DidDrawCheckLayer
* before
=
2852 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2853 if (testcase
.layer_before
.has_copy_request
)
2854 before
->AddCopyRequest();
2856 root
->AddChild(MissingTextureAnimatingLayer::Create(
2857 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2858 testcase
.layer_between
.has_incomplete_tile
,
2859 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2860 DidDrawCheckLayer
* between
=
2861 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2862 if (testcase
.layer_between
.has_copy_request
)
2863 between
->AddCopyRequest();
2865 root
->AddChild(MissingTextureAnimatingLayer::Create(
2866 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2867 testcase
.layer_after
.has_incomplete_tile
,
2868 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2869 DidDrawCheckLayer
* after
=
2870 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2871 if (testcase
.layer_after
.has_copy_request
)
2872 after
->AddCopyRequest();
2874 if (testcase
.high_res_required
)
2875 host_impl_
->SetRequiresHighResToDraw();
2877 LayerTreeHostImpl::FrameData frame
;
2878 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2879 host_impl_
->DrawLayers(&frame
);
2880 host_impl_
->DidDrawAllLayers(frame
);
2881 host_impl_
->SwapBuffers(frame
);
2885 TEST_F(LayerTreeHostImplTest
,
2886 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2887 CreateHostImpl(DefaultSettings(),
2888 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2889 EXPECT_TRUE(host_impl_
->output_surface()
2891 .draw_and_swap_full_viewport_every_frame
);
2893 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2896 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2897 // 1. Animation with missing tile.
2898 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2899 cases
.back().layer_between
.has_missing_tile
= true;
2900 cases
.back().layer_between
.is_animating
= true;
2901 // 2. High res required with incomplete tile.
2902 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2903 cases
.back().high_res_required
= true;
2904 cases
.back().layer_between
.has_incomplete_tile
= true;
2905 // 3. High res required with missing tile.
2906 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2907 cases
.back().high_res_required
= true;
2908 cases
.back().layer_between
.has_missing_tile
= true;
2910 host_impl_
->active_tree()->SetRootLayer(
2911 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2912 DidDrawCheckLayer
* root
=
2913 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2914 root
->SetHasRenderSurface(true);
2916 LayerTreeHostImpl::FrameData frame
;
2917 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2918 host_impl_
->DrawLayers(&frame
);
2919 host_impl_
->DidDrawAllLayers(frame
);
2920 host_impl_
->SwapBuffers(frame
);
2922 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2923 const auto& testcase
= cases
[i
];
2924 std::vector
<LayerImpl
*> to_remove
;
2925 for (auto* child
: root
->children())
2926 to_remove
.push_back(child
);
2927 for (auto* child
: to_remove
)
2928 root
->RemoveChild(child
);
2930 std::ostringstream scope
;
2931 scope
<< "Test case: " << i
;
2932 SCOPED_TRACE(scope
.str());
2934 root
->AddChild(MissingTextureAnimatingLayer::Create(
2935 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2936 testcase
.layer_before
.has_incomplete_tile
,
2937 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2938 DidDrawCheckLayer
* before
=
2939 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2940 if (testcase
.layer_before
.has_copy_request
)
2941 before
->AddCopyRequest();
2943 root
->AddChild(MissingTextureAnimatingLayer::Create(
2944 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2945 testcase
.layer_between
.has_incomplete_tile
,
2946 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2947 DidDrawCheckLayer
* between
=
2948 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2949 if (testcase
.layer_between
.has_copy_request
)
2950 between
->AddCopyRequest();
2952 root
->AddChild(MissingTextureAnimatingLayer::Create(
2953 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2954 testcase
.layer_after
.has_incomplete_tile
,
2955 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2956 DidDrawCheckLayer
* after
=
2957 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2958 if (testcase
.layer_after
.has_copy_request
)
2959 after
->AddCopyRequest();
2961 if (testcase
.high_res_required
)
2962 host_impl_
->SetRequiresHighResToDraw();
2964 LayerTreeHostImpl::FrameData frame
;
2965 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2966 host_impl_
->DrawLayers(&frame
);
2967 host_impl_
->DidDrawAllLayers(frame
);
2968 host_impl_
->SwapBuffers(frame
);
2972 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2973 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2974 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2975 root
->SetHasRenderSurface(true);
2976 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2979 // Scroll event is ignored because layer is not scrollable.
2980 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2981 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2982 EXPECT_FALSE(did_request_redraw_
);
2983 EXPECT_FALSE(did_request_commit_
);
2986 TEST_F(LayerTreeHostImplTest
, ClampingAfterActivation
) {
2987 host_impl_
->CreatePendingTree();
2988 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2989 CreateScrollAndContentsLayers(host_impl_
->pending_tree(),
2990 gfx::Size(100, 100));
2991 host_impl_
->ActivateSyncTree();
2993 host_impl_
->CreatePendingTree();
2994 const gfx::ScrollOffset pending_scroll
= gfx::ScrollOffset(-100, -100);
2995 LayerImpl
* active_outer_layer
=
2996 host_impl_
->active_tree()->OuterViewportScrollLayer();
2997 LayerImpl
* pending_outer_layer
=
2998 host_impl_
->pending_tree()->OuterViewportScrollLayer();
2999 pending_outer_layer
->PushScrollOffsetFromMainThread(pending_scroll
);
3001 host_impl_
->ActivateSyncTree();
3002 // Scrolloffsets on the active tree will be clamped after activation.
3003 EXPECT_EQ(active_outer_layer
->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
3006 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
3008 LayerTreeHostImplTopControlsTest()
3009 // Make the clip size the same as the layer (content) size so the layer is
3011 : layer_size_(10, 10),
3012 clip_size_(layer_size_
),
3013 top_controls_height_(50) {
3014 viewport_size_
= gfx::Size(clip_size_
.width(),
3015 clip_size_
.height() + top_controls_height_
);
3018 bool CreateHostImpl(const LayerTreeSettings
& settings
,
3019 scoped_ptr
<OutputSurface
> output_surface
) override
{
3021 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
3023 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
3024 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3025 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
3030 void SetupTopControlsAndScrollLayerWithVirtualViewport(
3031 const gfx::Size
& inner_viewport_size
,
3032 const gfx::Size
& outer_viewport_size
,
3033 const gfx::Size
& scroll_layer_size
) {
3034 CreateHostImpl(settings_
, CreateOutputSurface());
3035 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3036 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
3037 host_impl_
->DidChangeTopControlsPosition();
3039 scoped_ptr
<LayerImpl
> root
=
3040 LayerImpl::Create(host_impl_
->active_tree(), 1);
3041 scoped_ptr
<LayerImpl
> root_clip
=
3042 LayerImpl::Create(host_impl_
->active_tree(), 2);
3043 scoped_ptr
<LayerImpl
> page_scale
=
3044 LayerImpl::Create(host_impl_
->active_tree(), 3);
3046 scoped_ptr
<LayerImpl
> outer_scroll
=
3047 LayerImpl::Create(host_impl_
->active_tree(), 4);
3048 scoped_ptr
<LayerImpl
> outer_clip
=
3049 LayerImpl::Create(host_impl_
->active_tree(), 5);
3051 root_clip
->SetBounds(inner_viewport_size
);
3052 root
->SetScrollClipLayer(root_clip
->id());
3053 root
->SetBounds(outer_viewport_size
);
3054 root
->SetPosition(gfx::PointF());
3055 root
->SetDrawsContent(false);
3056 root
->SetIsContainerForFixedPositionLayers(true);
3057 root_clip
->SetHasRenderSurface(true);
3058 outer_clip
->SetBounds(outer_viewport_size
);
3059 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
3060 outer_scroll
->SetBounds(scroll_layer_size
);
3061 outer_scroll
->SetPosition(gfx::PointF());
3062 outer_scroll
->SetDrawsContent(false);
3063 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
3065 int inner_viewport_scroll_layer_id
= root
->id();
3066 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
3067 int page_scale_layer_id
= page_scale
->id();
3069 outer_clip
->AddChild(outer_scroll
.Pass());
3070 root
->AddChild(outer_clip
.Pass());
3071 page_scale
->AddChild(root
.Pass());
3072 root_clip
->AddChild(page_scale
.Pass());
3074 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3075 host_impl_
->active_tree()->SetViewportLayersFromIds(
3076 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
3077 outer_viewport_scroll_layer_id
);
3079 host_impl_
->SetViewportSize(inner_viewport_size
);
3080 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3081 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
3085 gfx::Size layer_size_
;
3086 gfx::Size clip_size_
;
3087 gfx::Size viewport_size_
;
3088 float top_controls_height_
;
3090 LayerTreeSettings settings_
;
3091 }; // class LayerTreeHostImplTopControlsTest
3093 // Tests that, on a page with content the same size as the viewport, hiding
3094 // the top controls also increases the ScrollableSize (i.e. the content size).
3095 // Since the viewport got larger, the effective scrollable "content" also did.
3096 // This ensures, for one thing, that the overscroll glow is shown in the right
3098 TEST_F(LayerTreeHostImplTopControlsTest
,
3099 HidingTopControlsExpandsScrollableSize
) {
3100 SetupTopControlsAndScrollLayerWithVirtualViewport(
3101 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
3103 LayerTreeImpl
* active_tree
= host_impl_
->active_tree();
3105 // Create a content layer beneath the outer viewport scroll layer.
3106 int id
= host_impl_
->OuterViewportScrollLayer()->id();
3107 host_impl_
->OuterViewportScrollLayer()->AddChild(
3108 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2));
3109 LayerImpl
* content
= active_tree
->OuterViewportScrollLayer()->children()[0];
3110 content
->SetBounds(gfx::Size(50, 50));
3114 LayerImpl
* inner_container
= active_tree
->InnerViewportContainerLayer();
3115 LayerImpl
* outer_container
= active_tree
->OuterViewportContainerLayer();
3117 // The top controls should start off showing so the viewport should be shrunk.
3118 ASSERT_EQ(gfx::Size(50, 50), inner_container
->bounds());
3119 ASSERT_EQ(gfx::Size(50, 50), outer_container
->bounds());
3121 EXPECT_EQ(gfx::SizeF(50, 50), active_tree
->ScrollableSize());
3123 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3124 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3126 host_impl_
->top_controls_manager()->ScrollBegin();
3128 // Hide the top controls by a bit, the scrollable size should increase but the
3129 // actual content bounds shouldn't.
3131 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3132 ASSERT_EQ(gfx::Size(50, 75), inner_container
->bounds());
3133 ASSERT_EQ(gfx::Size(50, 75), outer_container
->bounds());
3134 EXPECT_EQ(gfx::SizeF(50, 75), active_tree
->ScrollableSize());
3135 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3138 // Fully hide the top controls.
3140 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3141 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3142 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3143 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3144 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3147 // Scrolling additionally shouldn't have any effect.
3149 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3150 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3151 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3152 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3153 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3156 host_impl_
->top_controls_manager()->ScrollEnd();
3157 host_impl_
->ScrollEnd();
3160 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
3161 SetupTopControlsAndScrollLayerWithVirtualViewport(
3162 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
3165 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3166 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3168 // Make the test scroll delta a fractional amount, to verify that the
3169 // fixed container size delta is (1) non-zero, and (2) fractional, and
3170 // (3) matches the movement of the top controls.
3171 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
3172 host_impl_
->top_controls_manager()->ScrollBegin();
3173 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3174 host_impl_
->top_controls_manager()->ScrollEnd();
3176 LayerImpl
* inner_viewport_scroll_layer
=
3177 host_impl_
->active_tree()->InnerViewportScrollLayer();
3178 DCHECK(inner_viewport_scroll_layer
);
3179 host_impl_
->ScrollEnd();
3180 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3181 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3184 // In this test, the outer viewport is initially unscrollable. We test that a
3185 // scroll initiated on the inner viewport, causing the top controls to show and
3186 // thus making the outer viewport scrollable, still scrolls the outer viewport.
3187 TEST_F(LayerTreeHostImplTopControlsTest
,
3188 TopControlsOuterViewportBecomesScrollable
) {
3189 SetupTopControlsAndScrollLayerWithVirtualViewport(
3190 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
3193 LayerImpl
* inner_scroll
=
3194 host_impl_
->active_tree()->InnerViewportScrollLayer();
3195 LayerImpl
* inner_container
=
3196 host_impl_
->active_tree()->InnerViewportContainerLayer();
3197 LayerImpl
* outer_scroll
=
3198 host_impl_
->active_tree()->OuterViewportScrollLayer();
3199 LayerImpl
* outer_container
=
3200 host_impl_
->active_tree()->OuterViewportContainerLayer();
3202 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
3203 outer_scroll
->SetDrawsContent(true);
3204 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
3206 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3207 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3208 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
3210 // The entire scroll delta should have been used to hide the top controls.
3211 // The viewport layers should be resized back to their full sizes.
3212 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3213 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3214 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
3215 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
3217 // The inner viewport should be scrollable by 50px * page_scale.
3218 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
3219 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
3220 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3221 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
3223 host_impl_
->ScrollEnd();
3225 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3226 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3227 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
3229 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3231 // The entire scroll delta should have been used to show the top controls.
3232 // The outer viewport should be resized to accomodate and scrolled to the
3233 // bottom of the document to keep the viewport in place.
3234 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3235 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
3236 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
3237 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3238 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3240 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3241 // since it wasn't scrollable when the scroll began.
3242 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
3243 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3244 EXPECT_EQ(15.f
, inner_scroll
->CurrentScrollOffset().y());
3246 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
3247 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3248 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3250 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3251 host_impl_
->ScrollEnd();
3253 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3254 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3257 // Test that the fixed position container delta is appropriately adjusted
3258 // by the top controls showing/hiding and page scale doesn't affect it.
3259 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
3260 SetupTopControlsAndScrollLayerWithVirtualViewport(
3261 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3263 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3265 float page_scale
= 1.5f
;
3266 LayerImpl
* outer_viewport_scroll_layer
=
3267 host_impl_
->active_tree()->OuterViewportScrollLayer();
3269 // Zoom in, since the fixed container is the outer viewport, the delta should
3271 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3273 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3274 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3276 // Scroll down, the top controls hiding should expand the viewport size so
3277 // the delta should be equal to the scroll distance.
3278 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
3279 host_impl_
->top_controls_manager()->ScrollBegin();
3280 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3281 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
3282 host_impl_
->top_controls_manager()->ContentTopOffset());
3283 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3284 outer_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3285 host_impl_
->ScrollEnd();
3287 // Scroll past the maximum extent. The delta shouldn't be greater than the
3288 // top controls height.
3289 host_impl_
->top_controls_manager()->ScrollBegin();
3290 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3291 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3292 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3293 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3294 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
3295 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3296 host_impl_
->ScrollEnd();
3298 // Scroll in the direction to make the top controls show.
3299 host_impl_
->top_controls_manager()->ScrollBegin();
3300 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
3301 EXPECT_EQ(top_controls_scroll_delta
.y(),
3302 host_impl_
->top_controls_manager()->ContentTopOffset());
3304 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
3305 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3306 host_impl_
->top_controls_manager()->ScrollEnd();
3309 // Test that if only the top controls are scrolled, we shouldn't request a
3311 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsDontTriggerCommit
) {
3312 SetupTopControlsAndScrollLayerWithVirtualViewport(
3313 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3316 // Show top controls
3317 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3319 // Scroll 25px to hide top controls
3320 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3321 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3322 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3323 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3324 EXPECT_FALSE(did_request_commit_
);
3327 // Test that if a scrollable sublayer doesn't consume the scroll,
3328 // top controls should hide when scrolling down.
3329 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
3330 gfx::Size
sub_content_size(100, 400);
3331 gfx::Size
sub_content_layer_size(100, 300);
3332 SetupTopControlsAndScrollLayerWithVirtualViewport(
3333 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3336 // Show top controls
3337 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3339 LayerImpl
* outer_viewport_scroll_layer
=
3340 host_impl_
->active_tree()->OuterViewportScrollLayer();
3341 int id
= outer_viewport_scroll_layer
->id();
3343 scoped_ptr
<LayerImpl
> child
=
3344 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
3345 scoped_ptr
<LayerImpl
> child_clip
=
3346 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
3348 child_clip
->SetBounds(sub_content_layer_size
);
3349 child
->SetScrollClipLayer(child_clip
->id());
3350 child
->SetBounds(sub_content_size
);
3351 child
->SetPosition(gfx::PointF());
3352 child
->SetDrawsContent(true);
3353 child
->SetIsContainerForFixedPositionLayers(true);
3355 // scroll child to limit
3356 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
3357 child_clip
->AddChild(child
.Pass());
3358 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
3360 // Scroll 25px to hide top controls
3361 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3362 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3363 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3364 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3365 host_impl_
->ScrollEnd();
3367 // Top controls should be hidden
3368 EXPECT_EQ(scroll_delta
.y(),
3369 top_controls_height_
-
3370 host_impl_
->top_controls_manager()->ContentTopOffset());
3373 // Ensure setting the top controls position explicitly using the setters on the
3374 // TreeImpl correctly affects the top controls manager and viewport bounds.
3375 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
3376 CreateHostImpl(settings_
, CreateOutputSurface());
3377 SetupTopControlsAndScrollLayerWithVirtualViewport(
3378 layer_size_
, layer_size_
, layer_size_
);
3381 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3382 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3383 30.f
/ top_controls_height_
);
3384 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3385 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3386 EXPECT_FLOAT_EQ(-20.f
,
3387 host_impl_
->top_controls_manager()->ControlsTopOffset());
3389 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3390 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3391 EXPECT_FLOAT_EQ(-50.f
,
3392 host_impl_
->top_controls_manager()->ControlsTopOffset());
3394 host_impl_
->DidChangeTopControlsPosition();
3396 // Now that top controls have moved, expect the clip to resize.
3397 LayerImpl
* inner_clip_ptr
=
3398 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3399 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3402 // Test that the top_controls delta and sent delta are appropriately
3403 // applied on sync tree activation. The total top controls offset shouldn't
3404 // change after the activation.
3405 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
3406 CreateHostImpl(settings_
, CreateOutputSurface());
3407 SetupTopControlsAndScrollLayerWithVirtualViewport(
3408 layer_size_
, layer_size_
, layer_size_
);
3411 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3412 20.f
/ top_controls_height_
);
3413 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3414 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
3415 15.f
/ top_controls_height_
);
3416 host_impl_
->active_tree()
3417 ->top_controls_shown_ratio()
3418 ->PullDeltaForMainThread();
3419 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3420 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
3421 top_controls_height_
);
3423 host_impl_
->DidChangeTopControlsPosition();
3424 LayerImpl
* inner_clip_ptr
=
3425 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3426 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3427 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3429 host_impl_
->ActivateSyncTree();
3431 inner_clip_ptr
= host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3432 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3433 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3436 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
3437 top_controls_height_
);
3440 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3441 top_controls_height_
);
3444 // Test that changing the top controls layout height is correctly applied to
3445 // the inner viewport container bounds. That is, the top controls layout
3446 // height is the amount that the inner viewport container was shrunk outside
3447 // the compositor to accommodate the top controls.
3448 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
3449 CreateHostImpl(settings_
, CreateOutputSurface());
3450 SetupTopControlsAndScrollLayerWithVirtualViewport(
3451 layer_size_
, layer_size_
, layer_size_
);
3454 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
3455 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3457 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3459 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3460 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3462 host_impl_
->DidChangeTopControlsPosition();
3463 LayerImpl
* inner_clip_ptr
=
3464 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3465 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3466 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3468 host_impl_
->sync_tree()->root_layer()->SetBounds(
3469 gfx::Size(inner_clip_ptr
->bounds().width(),
3470 inner_clip_ptr
->bounds().height() - 50.f
));
3472 host_impl_
->ActivateSyncTree();
3475 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3476 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3478 // The total bounds should remain unchanged since the bounds delta should
3479 // account for the difference between the layout height and the current
3480 // top controls offset.
3481 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3482 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), inner_clip_ptr
->bounds_delta());
3484 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3485 host_impl_
->DidChangeTopControlsPosition();
3487 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
3488 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
3489 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3490 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), inner_clip_ptr
->bounds_delta());
3491 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
3492 inner_clip_ptr
->bounds());
3495 // Test that showing/hiding the top controls when the viewport is fully scrolled
3496 // doesn't incorrectly change the viewport offset due to clamping from changing
3498 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
3499 SetupTopControlsAndScrollLayerWithVirtualViewport(
3500 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3503 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3505 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3506 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3508 // Scroll the viewports to max scroll offset.
3509 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3510 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3512 gfx::ScrollOffset viewport_offset
=
3513 host_impl_
->active_tree()->TotalScrollOffset();
3514 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
3516 // Hide the top controls by 25px.
3517 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3518 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3519 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3520 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3522 // scrolling down at the max extents no longer hides the top controls
3523 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3525 // forcefully hide the top controls by 25px
3526 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3527 host_impl_
->ScrollEnd();
3529 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3530 top_controls_height_
-
3531 host_impl_
->top_controls_manager()->ContentTopOffset());
3533 inner_scroll
->ClampScrollToMaxScrollOffset();
3534 outer_scroll
->ClampScrollToMaxScrollOffset();
3536 // We should still be fully scrolled.
3537 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3538 host_impl_
->active_tree()->TotalScrollOffset());
3540 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3542 // Bring the top controls down by 25px.
3543 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3544 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3545 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3546 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3547 host_impl_
->ScrollEnd();
3549 // The viewport offset shouldn't have changed.
3550 EXPECT_EQ(viewport_offset
,
3551 host_impl_
->active_tree()->TotalScrollOffset());
3553 // Scroll the viewports to max scroll offset.
3554 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3555 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3556 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3557 host_impl_
->active_tree()->TotalScrollOffset());
3560 // Test that the top controls coming in and out maintains the same aspect ratio
3561 // between the inner and outer viewports.
3562 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3563 SetupTopControlsAndScrollLayerWithVirtualViewport(
3564 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3565 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 2.f
);
3568 EXPECT_FLOAT_EQ(top_controls_height_
,
3569 host_impl_
->top_controls_manager()->ContentTopOffset());
3571 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3572 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3573 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3574 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3575 host_impl_
->ScrollEnd();
3577 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3578 top_controls_height_
-
3579 host_impl_
->top_controls_manager()->ContentTopOffset());
3581 // Top controls were hidden by 25px so the inner viewport should have expanded
3583 LayerImpl
* outer_container
=
3584 host_impl_
->active_tree()->OuterViewportContainerLayer();
3585 LayerImpl
* inner_container
=
3586 host_impl_
->active_tree()->InnerViewportContainerLayer();
3587 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3589 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3590 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3591 inner_container
->BoundsForScrolling().height();
3592 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3593 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3595 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3598 // Test that scrolling the outer viewport affects the top controls.
3599 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3600 SetupTopControlsAndScrollLayerWithVirtualViewport(
3601 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3604 EXPECT_EQ(top_controls_height_
,
3605 host_impl_
->top_controls_manager()->ContentTopOffset());
3607 // Send a gesture scroll that will scroll the outer viewport, make sure the
3608 // top controls get scrolled.
3609 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3610 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3611 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3612 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3613 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3614 host_impl_
->CurrentlyScrollingLayer());
3615 host_impl_
->ScrollEnd();
3617 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3618 top_controls_height_
-
3619 host_impl_
->top_controls_manager()->ContentTopOffset());
3621 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3622 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3623 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3624 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3626 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3627 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3628 host_impl_
->CurrentlyScrollingLayer());
3630 host_impl_
->ScrollEnd();
3632 // Position the viewports such that the inner viewport will be scrolled.
3633 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3634 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3635 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3637 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3638 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3639 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3640 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3642 EXPECT_EQ(top_controls_height_
,
3643 host_impl_
->top_controls_manager()->ContentTopOffset());
3645 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3646 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3648 host_impl_
->ScrollEnd();
3651 TEST_F(LayerTreeHostImplTopControlsTest
,
3652 ScrollNonScrollableRootWithTopControls
) {
3653 CreateHostImpl(settings_
, CreateOutputSurface());
3654 SetupTopControlsAndScrollLayerWithVirtualViewport(
3655 layer_size_
, layer_size_
, layer_size_
);
3658 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3659 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3661 host_impl_
->top_controls_manager()->ScrollBegin();
3662 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3663 host_impl_
->top_controls_manager()->ScrollEnd();
3664 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3665 // Now that top controls have moved, expect the clip to resize.
3666 LayerImpl
* inner_clip_ptr
=
3667 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3668 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3670 host_impl_
->ScrollEnd();
3672 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3673 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3675 float scroll_increment_y
= -25.f
;
3676 host_impl_
->top_controls_manager()->ScrollBegin();
3677 host_impl_
->top_controls_manager()->ScrollBy(
3678 gfx::Vector2dF(0.f
, scroll_increment_y
));
3679 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3680 host_impl_
->top_controls_manager()->ContentTopOffset());
3681 // Now that top controls have moved, expect the clip to resize.
3682 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3683 viewport_size_
.height() + scroll_increment_y
),
3684 inner_clip_ptr
->bounds());
3686 host_impl_
->top_controls_manager()->ScrollBy(
3687 gfx::Vector2dF(0.f
, scroll_increment_y
));
3688 host_impl_
->top_controls_manager()->ScrollEnd();
3689 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3690 host_impl_
->top_controls_manager()->ContentTopOffset());
3691 // Now that top controls have moved, expect the clip to resize.
3692 EXPECT_EQ(clip_size_
, inner_clip_ptr
->bounds());
3694 host_impl_
->ScrollEnd();
3696 // Verify the layer is once-again non-scrollable.
3698 gfx::ScrollOffset(),
3699 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3701 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3702 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3705 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3706 // Test the configuration where a non-composited root layer is embedded in a
3707 // scrollable outer layer.
3708 gfx::Size
surface_size(10, 10);
3709 gfx::Size
contents_size(20, 20);
3711 scoped_ptr
<LayerImpl
> content_layer
=
3712 LayerImpl::Create(host_impl_
->active_tree(), 1);
3713 content_layer
->SetDrawsContent(true);
3714 content_layer
->SetPosition(gfx::PointF());
3715 content_layer
->SetBounds(contents_size
);
3717 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3718 LayerImpl::Create(host_impl_
->active_tree(), 3);
3719 scroll_clip_layer
->SetBounds(surface_size
);
3721 scoped_ptr
<LayerImpl
> scroll_layer
=
3722 LayerImpl::Create(host_impl_
->active_tree(), 2);
3723 scroll_layer
->SetScrollClipLayer(3);
3724 scroll_layer
->SetBounds(contents_size
);
3725 scroll_layer
->SetPosition(gfx::PointF());
3726 scroll_layer
->AddChild(content_layer
.Pass());
3727 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3729 scroll_clip_layer
->SetHasRenderSurface(true);
3730 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3731 host_impl_
->SetViewportSize(surface_size
);
3734 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3735 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3736 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3737 host_impl_
->ScrollEnd();
3738 EXPECT_TRUE(did_request_redraw_
);
3739 EXPECT_TRUE(did_request_commit_
);
3742 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3743 gfx::Size
surface_size(10, 10);
3744 gfx::Size
contents_size(20, 20);
3745 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3746 root
->SetBounds(surface_size
);
3747 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3748 root
->SetHasRenderSurface(true);
3749 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3750 host_impl_
->SetViewportSize(surface_size
);
3753 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3754 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3755 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3756 host_impl_
->ScrollEnd();
3757 EXPECT_TRUE(did_request_redraw_
);
3758 EXPECT_TRUE(did_request_commit_
);
3761 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3762 gfx::Size
surface_size(10, 10);
3763 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3764 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3765 root
->SetHasRenderSurface(true);
3766 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3767 host_impl_
->SetViewportSize(surface_size
);
3770 // Scroll event is ignored because the input coordinate is outside the layer
3772 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3773 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3774 EXPECT_FALSE(did_request_redraw_
);
3775 EXPECT_FALSE(did_request_commit_
);
3778 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3779 gfx::Size
surface_size(10, 10);
3780 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3781 root
->SetHasRenderSurface(true);
3782 scoped_ptr
<LayerImpl
> child
=
3783 CreateScrollableLayer(2, surface_size
, root
.get());
3784 host_impl_
->SetViewportSize(surface_size
);
3786 gfx::Transform matrix
;
3787 matrix
.RotateAboutXAxis(180.0);
3788 child
->SetTransform(matrix
);
3789 child
->SetDoubleSided(false);
3791 root
->AddChild(child
.Pass());
3792 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3795 // Scroll event is ignored because the scrollable layer is not facing the
3796 // viewer and there is nothing scrollable behind it.
3797 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3798 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3799 EXPECT_FALSE(did_request_redraw_
);
3800 EXPECT_FALSE(did_request_commit_
);
3803 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3804 gfx::Size
surface_size(10, 10);
3805 scoped_ptr
<LayerImpl
> clip_layer
=
3806 LayerImpl::Create(host_impl_
->active_tree(), 3);
3807 scoped_ptr
<LayerImpl
> content_layer
=
3808 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3809 content_layer
->SetShouldScrollOnMainThread(true);
3810 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3812 // Note: we can use the same clip layer for both since both calls to
3813 // CreateScrollableLayer() use the same surface size.
3814 scoped_ptr
<LayerImpl
> scroll_layer
=
3815 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3816 scroll_layer
->AddChild(content_layer
.Pass());
3817 clip_layer
->AddChild(scroll_layer
.Pass());
3818 clip_layer
->SetHasRenderSurface(true);
3820 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3821 host_impl_
->SetViewportSize(surface_size
);
3824 // Scrolling fails because the content layer is asking to be scrolled on the
3826 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3827 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3830 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3831 gfx::Size
viewport_size(20, 20);
3832 float page_scale
= 2.f
;
3834 SetupScrollAndContentsLayers(viewport_size
);
3836 // Setup the layers so that the outer viewport is scrollable.
3837 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3839 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3841 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3844 LayerImpl
* root_scroll
=
3845 host_impl_
->active_tree()->OuterViewportScrollLayer();
3846 LayerImpl
* inner_scroll
=
3847 host_impl_
->active_tree()->InnerViewportScrollLayer();
3848 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3850 gfx::Vector2d
scroll_delta(0, 10);
3851 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3852 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3853 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3854 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3855 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3856 host_impl_
->ScrollEnd();
3858 // Set new page scale from main thread.
3859 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3861 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3862 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3863 expected_scroll_delta
));
3865 // The scroll range should also have been updated.
3866 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3868 // The page scale delta remains constant because the impl thread did not
3870 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3873 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3874 gfx::Size
viewport_size(20, 20);
3875 float page_scale
= 2.f
;
3877 SetupScrollAndContentsLayers(viewport_size
);
3879 // Setup the layers so that the outer viewport is scrollable.
3880 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3882 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3884 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3887 LayerImpl
* root_scroll
=
3888 host_impl_
->active_tree()->OuterViewportScrollLayer();
3889 LayerImpl
* inner_scroll
=
3890 host_impl_
->active_tree()->InnerViewportScrollLayer();
3891 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3893 gfx::Vector2d
scroll_delta(0, 10);
3894 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3895 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3896 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3897 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3898 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3899 host_impl_
->ScrollEnd();
3901 // Set new page scale on impl thread by pinching.
3902 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3903 host_impl_
->PinchGestureBegin();
3904 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3905 host_impl_
->PinchGestureEnd();
3906 host_impl_
->ScrollEnd();
3909 // The scroll delta is not scaled because the main thread did not scale.
3910 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3911 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3912 expected_scroll_delta
));
3914 // The scroll range should also have been updated.
3915 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3917 // The page scale delta should match the new scale on the impl side.
3918 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3921 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3922 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3923 gfx::Size
surface_size(10, 10);
3924 float default_page_scale
= 1.f
;
3925 gfx::Transform default_page_scale_matrix
;
3926 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3928 float new_page_scale
= 2.f
;
3929 gfx::Transform new_page_scale_matrix
;
3930 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3932 // Create a normal scrollable root layer and another scrollable child layer.
3933 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3934 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3935 LayerImpl
* child
= scroll
->children()[0];
3937 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3938 LayerImpl::Create(host_impl_
->active_tree(), 6);
3939 scoped_ptr
<LayerImpl
> scrollable_child
=
3940 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3941 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3942 child
->AddChild(scrollable_child_clip
.Pass());
3943 LayerImpl
* grand_child
= child
->children()[0];
3945 // Set new page scale on impl thread by pinching.
3946 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3947 host_impl_
->PinchGestureBegin();
3948 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3949 host_impl_
->PinchGestureEnd();
3950 host_impl_
->ScrollEnd();
3953 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3954 // the page scale delta on the root layer is applied hierarchically.
3955 LayerTreeHostImpl::FrameData frame
;
3956 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3957 host_impl_
->DrawLayers(&frame
);
3958 host_impl_
->DidDrawAllLayers(frame
);
3960 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3961 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3962 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3963 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3964 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3965 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3966 EXPECT_EQ(new_page_scale
,
3967 grand_child
->draw_transform().matrix().getDouble(0, 0));
3968 EXPECT_EQ(new_page_scale
,
3969 grand_child
->draw_transform().matrix().getDouble(1, 1));
3972 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3973 SetupScrollAndContentsLayers(gfx::Size(30, 30));
3975 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3976 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3978 // Make the outer scroll layer scrollable.
3979 outer_scroll
->SetBounds(gfx::Size(50, 50));
3983 gfx::Vector2d
scroll_delta(0, 10);
3984 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3985 gfx::ScrollOffset
expected_max_scroll(outer_scroll
->MaxScrollOffset());
3986 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3987 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3988 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3989 host_impl_
->ScrollEnd();
3991 float page_scale
= 2.f
;
3992 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3997 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3998 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3999 expected_scroll_delta
));
4001 // The scroll range should not have changed.
4002 EXPECT_EQ(outer_scroll
->MaxScrollOffset(), expected_max_scroll
);
4004 // The page scale delta remains constant because the impl thread did not
4006 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
4009 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
4010 // Scroll a child layer beyond its maximum scroll range and make sure the
4011 // parent layer is scrolled on the axis on which the child was unable to
4013 gfx::Size
surface_size(10, 10);
4014 gfx::Size
content_size(20, 20);
4015 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4016 root
->SetBounds(surface_size
);
4017 root
->SetHasRenderSurface(true);
4018 scoped_ptr
<LayerImpl
> grand_child
=
4019 CreateScrollableLayer(3, content_size
, root
.get());
4021 scoped_ptr
<LayerImpl
> child
=
4022 CreateScrollableLayer(2, content_size
, root
.get());
4023 LayerImpl
* grand_child_layer
= grand_child
.get();
4024 child
->AddChild(grand_child
.Pass());
4026 LayerImpl
* child_layer
= child
.get();
4027 root
->AddChild(child
.Pass());
4028 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4029 host_impl_
->active_tree()->DidBecomeActive();
4030 host_impl_
->SetViewportSize(surface_size
);
4031 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
4032 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
4036 gfx::Vector2d
scroll_delta(-8, -7);
4037 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4038 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4039 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4040 host_impl_
->ScrollEnd();
4042 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4043 host_impl_
->ProcessScrollDeltas();
4045 // The grand child should have scrolled up to its limit.
4046 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
4047 LayerImpl
* grand_child
= child
->children()[0];
4048 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4049 gfx::Vector2d(0, -5)));
4051 // The child should have only scrolled on the other axis.
4052 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4053 gfx::Vector2d(-3, 0)));
4057 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
4058 // Scroll a child layer beyond its maximum scroll range and make sure the
4059 // the scroll doesn't bubble up to the parent layer.
4060 gfx::Size
surface_size(20, 20);
4061 gfx::Size
viewport_size(10, 10);
4062 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4063 root
->SetHasRenderSurface(true);
4064 scoped_ptr
<LayerImpl
> root_scrolling
=
4065 CreateScrollableLayer(2, surface_size
, root
.get());
4066 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
4068 scoped_ptr
<LayerImpl
> grand_child
=
4069 CreateScrollableLayer(4, surface_size
, root
.get());
4071 scoped_ptr
<LayerImpl
> child
=
4072 CreateScrollableLayer(3, surface_size
, root
.get());
4073 LayerImpl
* grand_child_layer
= grand_child
.get();
4074 child
->AddChild(grand_child
.Pass());
4076 LayerImpl
* child_layer
= child
.get();
4077 root_scrolling
->AddChild(child
.Pass());
4078 root
->AddChild(root_scrolling
.Pass());
4079 EXPECT_EQ(viewport_size
, root
->bounds());
4080 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4081 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4083 host_impl_
->active_tree()->DidBecomeActive();
4084 host_impl_
->SetViewportSize(viewport_size
);
4086 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4087 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4091 gfx::Vector2d
scroll_delta(0, -10);
4092 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4093 host_impl_
->ScrollBegin(gfx::Point(),
4094 InputHandler::NON_BUBBLING_GESTURE
));
4095 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4096 host_impl_
->ScrollEnd();
4098 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4099 host_impl_
->ProcessScrollDeltas();
4101 // The grand child should have scrolled up to its limit.
4103 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
4104 LayerImpl
* grand_child
= child
->children()[0];
4105 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4106 gfx::Vector2d(0, -2)));
4108 // The child should not have scrolled.
4109 ExpectNone(*scroll_info
.get(), child
->id());
4111 // The next time we scroll we should only scroll the parent.
4112 scroll_delta
= gfx::Vector2d(0, -3);
4113 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4114 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4115 InputHandler::NON_BUBBLING_GESTURE
));
4116 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4117 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4118 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
4119 host_impl_
->ScrollEnd();
4121 scroll_info
= host_impl_
->ProcessScrollDeltas();
4123 // The child should have scrolled up to its limit.
4124 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4125 gfx::Vector2d(0, -3)));
4127 // The grand child should not have scrolled.
4128 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4129 gfx::Vector2d(0, -2)));
4131 // After scrolling the parent, another scroll on the opposite direction
4132 // should still scroll the child.
4133 scroll_delta
= gfx::Vector2d(0, 7);
4134 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4135 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4136 InputHandler::NON_BUBBLING_GESTURE
));
4137 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4138 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4139 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4140 host_impl_
->ScrollEnd();
4142 scroll_info
= host_impl_
->ProcessScrollDeltas();
4144 // The grand child should have scrolled.
4145 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4146 gfx::Vector2d(0, 5)));
4148 // The child should not have scrolled.
4149 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4150 gfx::Vector2d(0, -3)));
4152 // Scrolling should be adjusted from viewport space.
4153 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
4154 host_impl_
->active_tree()->SetPageScaleOnActiveTree(2.f
);
4156 scroll_delta
= gfx::Vector2d(0, -2);
4157 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4158 host_impl_
->ScrollBegin(gfx::Point(1, 1),
4159 InputHandler::NON_BUBBLING_GESTURE
));
4160 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
4161 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4162 host_impl_
->ScrollEnd();
4164 scroll_info
= host_impl_
->ProcessScrollDeltas();
4166 // Should have scrolled by half the amount in layer space (5 - 2/2)
4167 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4168 gfx::Vector2d(0, 4)));
4171 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
4172 // When we try to scroll a non-scrollable child layer, the scroll delta
4173 // should be applied to one of its ancestors if possible.
4174 gfx::Size
surface_size(10, 10);
4175 gfx::Size
content_size(20, 20);
4176 scoped_ptr
<LayerImpl
> root_clip
=
4177 LayerImpl::Create(host_impl_
->active_tree(), 3);
4178 root_clip
->SetHasRenderSurface(true);
4179 scoped_ptr
<LayerImpl
> root
=
4180 CreateScrollableLayer(1, content_size
, root_clip
.get());
4181 // Make 'root' the clip layer for child: since they have the same sizes the
4182 // child will have zero max_scroll_offset and scrolls will bubble.
4183 scoped_ptr
<LayerImpl
> child
=
4184 CreateScrollableLayer(2, content_size
, root
.get());
4185 child
->SetIsContainerForFixedPositionLayers(true);
4186 root
->SetBounds(content_size
);
4188 int root_scroll_id
= root
->id();
4189 root
->AddChild(child
.Pass());
4190 root_clip
->AddChild(root
.Pass());
4192 host_impl_
->SetViewportSize(surface_size
);
4193 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4194 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
4196 host_impl_
->active_tree()->DidBecomeActive();
4199 gfx::Vector2d
scroll_delta(0, 4);
4200 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4201 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4202 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4203 host_impl_
->ScrollEnd();
4205 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4206 host_impl_
->ProcessScrollDeltas();
4208 // Only the root scroll should have scrolled.
4209 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
4211 ScrollInfoContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
));
4215 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
4216 gfx::Size
surface_size(10, 10);
4217 scoped_ptr
<LayerImpl
> root_clip
=
4218 LayerImpl::Create(host_impl_
->active_tree(), 1);
4219 scoped_ptr
<LayerImpl
> root_scroll
=
4220 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4221 root_scroll
->SetIsContainerForFixedPositionLayers(true);
4222 root_clip
->SetHasRenderSurface(true);
4223 root_clip
->AddChild(root_scroll
.Pass());
4224 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4225 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4227 host_impl_
->active_tree()->DidBecomeActive();
4228 host_impl_
->SetViewportSize(surface_size
);
4230 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4233 host_impl_
->active_tree()->DetachLayerTree();
4234 scoped_ptr
<LayerImpl
> root_clip2
=
4235 LayerImpl::Create(host_impl_
->active_tree(), 3);
4236 scoped_ptr
<LayerImpl
> root_scroll2
=
4237 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
4238 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
4239 root_clip2
->AddChild(root_scroll2
.Pass());
4240 root_clip2
->SetHasRenderSurface(true);
4241 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
4242 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
4244 host_impl_
->active_tree()->DidBecomeActive();
4246 // Scrolling should still work even though we did not draw yet.
4247 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4248 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4251 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
4252 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4254 // Rotate the root layer 90 degrees counter-clockwise about its center.
4255 gfx::Transform rotate_transform
;
4256 rotate_transform
.Rotate(-90.0);
4257 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
4259 gfx::Size
surface_size(50, 50);
4260 host_impl_
->SetViewportSize(surface_size
);
4263 // Scroll to the right in screen coordinates with a gesture.
4264 gfx::Vector2d
gesture_scroll_delta(10, 0);
4265 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4266 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4267 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4268 host_impl_
->ScrollEnd();
4270 // The layer should have scrolled down in its local coordinates.
4271 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4272 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4273 gfx::Vector2d(0, gesture_scroll_delta
.x())));
4275 // Reset and scroll down with the wheel.
4276 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4277 gfx::Vector2d
wheel_scroll_delta(0, 10);
4278 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4279 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4280 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4281 host_impl_
->ScrollEnd();
4283 // The layer should have scrolled down in its local coordinates.
4284 scroll_info
= host_impl_
->ProcessScrollDeltas();
4285 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4286 wheel_scroll_delta
));
4289 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
4290 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4291 int child_clip_layer_id
= 6;
4292 int child_layer_id
= 7;
4293 float child_layer_angle
= -20.f
;
4295 // Create a child layer that is rotated to a non-axis-aligned angle.
4296 scoped_ptr
<LayerImpl
> clip_layer
=
4297 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4298 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4299 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4300 gfx::Transform rotate_transform
;
4301 rotate_transform
.Translate(-50.0, -50.0);
4302 rotate_transform
.Rotate(child_layer_angle
);
4303 rotate_transform
.Translate(50.0, 50.0);
4304 clip_layer
->SetTransform(rotate_transform
);
4306 // Only allow vertical scrolling.
4307 clip_layer
->SetBounds(
4308 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
4309 // The rotation depends on the layer's transform origin, and the child layer
4310 // is a different size than the clip, so make sure the clip layer's origin
4311 // lines up over the child.
4312 clip_layer
->SetTransformOrigin(gfx::Point3F(
4313 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
4314 LayerImpl
* child_ptr
= child
.get();
4315 clip_layer
->AddChild(child
.Pass());
4316 scroll_layer
->AddChild(clip_layer
.Pass());
4318 gfx::Size
surface_size(50, 50);
4319 host_impl_
->SetViewportSize(surface_size
);
4322 // Scroll down in screen coordinates with a gesture.
4323 gfx::Vector2d
gesture_scroll_delta(0, 10);
4324 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4325 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4326 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4327 host_impl_
->ScrollEnd();
4329 // The child layer should have scrolled down in its local coordinates an
4330 // amount proportional to the angle between it and the input scroll delta.
4331 gfx::Vector2d
expected_scroll_delta(
4332 0, gesture_scroll_delta
.y() *
4333 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
4334 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4335 host_impl_
->ProcessScrollDeltas();
4336 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4337 expected_scroll_delta
));
4339 // The root scroll layer should not have scrolled, because the input delta
4340 // was close to the layer's axis of movement.
4341 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4344 // Now reset and scroll the same amount horizontally.
4345 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4346 gfx::Vector2d
gesture_scroll_delta(10, 0);
4347 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4348 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4349 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4350 host_impl_
->ScrollEnd();
4352 // The child layer should have scrolled down in its local coordinates an
4353 // amount proportional to the angle between it and the input scroll delta.
4354 gfx::Vector2d
expected_scroll_delta(
4355 0, -gesture_scroll_delta
.x() *
4356 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
4357 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4358 host_impl_
->ProcessScrollDeltas();
4359 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4360 expected_scroll_delta
));
4362 // The root scroll layer should have scrolled more, since the input scroll
4363 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4364 gfx::Vector2d
expected_root_scroll_delta(
4365 gesture_scroll_delta
.x() *
4366 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
4368 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4369 expected_root_scroll_delta
));
4373 TEST_F(LayerTreeHostImplTest
, ScrollPerspectiveTransformedLayer
) {
4374 // When scrolling an element with perspective, the distance scrolled
4375 // depends on the point at which the scroll begins.
4376 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4377 int child_clip_layer_id
= 6;
4378 int child_layer_id
= 7;
4380 // Create a child layer that is rotated on its x axis, with perspective.
4381 scoped_ptr
<LayerImpl
> clip_layer
=
4382 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4383 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4384 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4385 LayerImpl
* child_ptr
= child
.get();
4386 gfx::Transform perspective_transform
;
4387 perspective_transform
.Translate(-50.0, -50.0);
4388 perspective_transform
.ApplyPerspectiveDepth(20);
4389 perspective_transform
.RotateAboutXAxis(45);
4390 perspective_transform
.Translate(50.0, 50.0);
4391 clip_layer
->SetTransform(perspective_transform
);
4393 clip_layer
->SetBounds(gfx::Size(child_ptr
->bounds().width() / 2,
4394 child_ptr
->bounds().height() / 2));
4395 // The transform depends on the layer's transform origin, and the child layer
4396 // is a different size than the clip, so make sure the clip layer's origin
4397 // lines up over the child.
4398 clip_layer
->SetTransformOrigin(gfx::Point3F(
4399 clip_layer
->bounds().width(), clip_layer
->bounds().height(), 0.f
));
4400 clip_layer
->AddChild(child
.Pass());
4401 scroll_layer
->AddChild(clip_layer
.Pass());
4403 gfx::Size
surface_size(50, 50);
4404 host_impl_
->SetViewportSize(surface_size
);
4406 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
4408 gfx::Vector2d gesture_scroll_deltas
[4];
4409 gesture_scroll_deltas
[0] = gfx::Vector2d(4, 10);
4410 gesture_scroll_deltas
[1] = gfx::Vector2d(4, 10);
4411 gesture_scroll_deltas
[2] = gfx::Vector2d(10, 0);
4412 gesture_scroll_deltas
[3] = gfx::Vector2d(10, 0);
4414 gfx::Vector2d expected_scroll_deltas
[4];
4415 // Perspective affects the vertical delta by a different
4416 // amount depending on the vertical position of the |viewport_point|.
4417 expected_scroll_deltas
[0] = gfx::Vector2d(2, 8);
4418 expected_scroll_deltas
[1] = gfx::Vector2d(1, 4);
4419 // Deltas which start with the same vertical position of the
4420 // |viewport_point| are subject to identical perspective effects.
4421 expected_scroll_deltas
[2] = gfx::Vector2d(4, 0);
4422 expected_scroll_deltas
[3] = gfx::Vector2d(4, 0);
4424 gfx::Point
viewport_point(1, 1);
4426 // Scroll in screen coordinates with a gesture. Each scroll starts
4427 // where the previous scroll ended, but the scroll position is reset
4429 for (int i
= 0; i
< 4; ++i
) {
4430 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4432 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4433 host_impl_
->ScrollBegin(viewport_point
, InputHandler::GESTURE
));
4434 host_impl_
->ScrollBy(viewport_point
, gesture_scroll_deltas
[i
]);
4435 viewport_point
+= gesture_scroll_deltas
[i
];
4436 host_impl_
->ScrollEnd();
4438 scroll_info
= host_impl_
->ProcessScrollDeltas();
4439 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4440 expected_scroll_deltas
[i
]));
4442 // The root scroll layer should not have scrolled, because the input delta
4443 // was close to the layer's axis of movement.
4444 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4448 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
4449 LayerImpl
* scroll_layer
=
4450 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4452 // Scale the layer to twice its normal size.
4454 gfx::Transform scale_transform
;
4455 scale_transform
.Scale(scale
, scale
);
4456 scroll_layer
->SetTransform(scale_transform
);
4458 gfx::Size
surface_size(50, 50);
4459 host_impl_
->SetViewportSize(surface_size
);
4462 // Scroll down in screen coordinates with a gesture.
4463 gfx::Vector2d
scroll_delta(0, 10);
4464 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4465 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4466 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4467 host_impl_
->ScrollEnd();
4469 // The layer should have scrolled down in its local coordinates, but half the
4471 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4472 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4473 gfx::Vector2d(0, scroll_delta
.y() / scale
)));
4475 // Reset and scroll down with the wheel.
4476 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4477 gfx::Vector2d
wheel_scroll_delta(0, 10);
4478 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4479 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4480 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4481 host_impl_
->ScrollEnd();
4483 // It should apply the scale factor to the scroll delta for the wheel event.
4484 scroll_info
= host_impl_
->ProcessScrollDeltas();
4485 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4486 wheel_scroll_delta
));
4489 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
4493 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
4494 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
4495 gfx::Size(width
* scale
- 1, height
* scale
));
4496 host_impl_
->SetDeviceScaleFactor(scale
);
4497 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4499 LayerImpl
* inner_viewport_scroll_layer
=
4500 host_impl_
->active_tree()->InnerViewportScrollLayer();
4501 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4502 inner_viewport_scroll_layer
->MaxScrollOffset());
4505 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
4507 TestScrollOffsetDelegate()
4508 : page_scale_factor_(0.f
),
4509 min_page_scale_factor_(-1.f
),
4510 max_page_scale_factor_(-1.f
) {}
4512 ~TestScrollOffsetDelegate() override
{}
4514 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
4515 const gfx::ScrollOffset
& max_scroll_offset
,
4516 const gfx::SizeF
& scrollable_size
,
4517 float page_scale_factor
,
4518 float min_page_scale_factor
,
4519 float max_page_scale_factor
) override
{
4520 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
4521 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
4522 last_set_scroll_offset_
= total_scroll_offset
;
4523 max_scroll_offset_
= max_scroll_offset
;
4524 scrollable_size_
= scrollable_size
;
4525 page_scale_factor_
= page_scale_factor
;
4526 min_page_scale_factor_
= min_page_scale_factor
;
4527 max_page_scale_factor_
= max_page_scale_factor
;
4530 gfx::ScrollOffset
last_set_scroll_offset() {
4531 return last_set_scroll_offset_
;
4534 gfx::ScrollOffset
max_scroll_offset() const {
4535 return max_scroll_offset_
;
4538 gfx::SizeF
scrollable_size() const {
4539 return scrollable_size_
;
4542 float page_scale_factor() const {
4543 return page_scale_factor_
;
4546 float min_page_scale_factor() const {
4547 return min_page_scale_factor_
;
4550 float max_page_scale_factor() const {
4551 return max_page_scale_factor_
;
4555 gfx::ScrollOffset last_set_scroll_offset_
;
4556 gfx::ScrollOffset max_scroll_offset_
;
4557 gfx::SizeF scrollable_size_
;
4558 float page_scale_factor_
;
4559 float min_page_scale_factor_
;
4560 float max_page_scale_factor_
;
4563 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4564 TestScrollOffsetDelegate scroll_delegate
;
4565 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4566 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4567 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4568 clip_layer
->SetBounds(gfx::Size(10, 20));
4570 // Setting the delegate results in the current scroll offset being set.
4571 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4572 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4573 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4574 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4575 EXPECT_EQ(initial_scroll_delta
.ToString(),
4576 scroll_delegate
.last_set_scroll_offset().ToString());
4578 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4579 // page_scale_factor and {min|max}_page_scale_factor being set.
4580 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4581 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4582 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4583 EXPECT_EQ(1.f
, scroll_delegate
.min_page_scale_factor());
4584 EXPECT_EQ(1.f
, scroll_delegate
.max_page_scale_factor());
4586 // Updating page scale immediately updates the delegate.
4587 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4588 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4589 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4590 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4591 host_impl_
->active_tree()->SetPageScaleOnActiveTree(2.f
* 1.5f
);
4592 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
4593 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4594 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4595 host_impl_
->active_tree()->SetPageScaleOnActiveTree(2.f
);
4596 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4597 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4598 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4599 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4601 // The pinch gesture doesn't put the delegate into a state where the scroll
4602 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4604 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4605 host_impl_
->PinchGestureBegin();
4606 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4607 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4608 host_impl_
->PinchGestureEnd();
4609 host_impl_
->ScrollEnd();
4611 // Scrolling should be relative to the offset as given by the delegate.
4612 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4613 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4615 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4616 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4617 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4619 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4620 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4621 scroll_delegate
.last_set_scroll_offset());
4623 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4624 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4625 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4626 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4627 scroll_delegate
.last_set_scroll_offset());
4628 host_impl_
->ScrollEnd();
4629 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(gfx::ScrollOffset());
4631 // Forces a full tree synchronization and ensures that the scroll delegate
4632 // sees the correct size of the new tree.
4633 gfx::Size
new_size(42, 24);
4634 host_impl_
->CreatePendingTree();
4635 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
4636 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4637 host_impl_
->ActivateSyncTree();
4638 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4640 // Un-setting the delegate should propagate the delegate's current offset to
4641 // the root scrollable layer.
4642 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4643 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4644 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4646 EXPECT_EQ(current_offset
.ToString(),
4647 scroll_layer
->CurrentScrollOffset().ToString());
4650 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4651 const gfx::Transform target_space_transform
=
4652 layer
->draw_properties().target_space_transform
;
4653 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4654 gfx::Point translated_point
;
4655 target_space_transform
.TransformPoint(&translated_point
);
4656 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4657 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4660 TEST_F(LayerTreeHostImplTest
,
4661 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4662 TestScrollOffsetDelegate scroll_delegate
;
4663 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4664 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4665 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4666 clip_layer
->SetBounds(gfx::Size(10, 20));
4667 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4669 // Draw first frame to clear any pending draws and check scroll.
4671 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4672 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4674 // Set external scroll delta on delegate and notify LayerTreeHost.
4675 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4676 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(scroll_offset
);
4678 // Check scroll delta reflected in layer.
4679 LayerTreeHostImpl::FrameData frame
;
4680 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4681 host_impl_
->DrawLayers(&frame
);
4682 host_impl_
->DidDrawAllLayers(frame
);
4683 EXPECT_FALSE(frame
.has_no_damage
);
4684 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4686 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4689 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4690 InputHandlerScrollResult scroll_result
;
4691 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4692 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4693 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4695 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4697 // In-bounds scrolling does not affect overscroll.
4698 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4699 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4700 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4701 EXPECT_TRUE(scroll_result
.did_scroll
);
4702 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4703 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4704 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4706 // Overscroll events are reflected immediately.
4707 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4708 EXPECT_TRUE(scroll_result
.did_scroll
);
4709 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4710 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4711 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4712 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4713 host_impl_
->accumulated_root_overscroll());
4715 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4716 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4717 EXPECT_TRUE(scroll_result
.did_scroll
);
4718 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4719 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4720 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4721 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4722 host_impl_
->accumulated_root_overscroll());
4724 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4725 EXPECT_FALSE(scroll_result
.did_scroll
);
4726 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4727 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4728 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4729 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4730 host_impl_
->accumulated_root_overscroll());
4732 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4733 EXPECT_TRUE(scroll_result
.did_scroll
);
4734 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4735 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4736 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4737 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4738 host_impl_
->accumulated_root_overscroll());
4740 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4741 EXPECT_TRUE(scroll_result
.did_scroll
);
4742 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4743 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4744 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4745 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4746 host_impl_
->accumulated_root_overscroll());
4748 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4749 EXPECT_TRUE(scroll_result
.did_scroll
);
4750 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4751 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4752 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4753 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4754 host_impl_
->accumulated_root_overscroll());
4756 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4757 EXPECT_TRUE(scroll_result
.did_scroll
);
4758 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4759 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4760 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4761 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4762 host_impl_
->accumulated_root_overscroll());
4764 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4765 // as no scroll occurs.
4766 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4767 EXPECT_FALSE(scroll_result
.did_scroll
);
4768 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4769 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4770 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4771 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4772 host_impl_
->accumulated_root_overscroll());
4774 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4775 EXPECT_FALSE(scroll_result
.did_scroll
);
4776 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4777 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4778 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4779 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4780 host_impl_
->accumulated_root_overscroll());
4782 // Overscroll resets on valid scroll.
4783 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4784 EXPECT_TRUE(scroll_result
.did_scroll
);
4785 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4786 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4787 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4788 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4789 host_impl_
->accumulated_root_overscroll());
4791 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4792 EXPECT_TRUE(scroll_result
.did_scroll
);
4793 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4794 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4795 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4796 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4797 host_impl_
->accumulated_root_overscroll());
4799 host_impl_
->ScrollEnd();
4803 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4804 // Scroll child layers beyond their maximum scroll range and make sure root
4805 // overscroll does not accumulate.
4806 InputHandlerScrollResult scroll_result
;
4807 gfx::Size
surface_size(10, 10);
4808 scoped_ptr
<LayerImpl
> root_clip
=
4809 LayerImpl::Create(host_impl_
->active_tree(), 4);
4810 root_clip
->SetHasRenderSurface(true);
4812 scoped_ptr
<LayerImpl
> root
=
4813 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4815 scoped_ptr
<LayerImpl
> grand_child
=
4816 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4818 scoped_ptr
<LayerImpl
> child
=
4819 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4820 LayerImpl
* grand_child_layer
= grand_child
.get();
4821 child
->AddChild(grand_child
.Pass());
4823 LayerImpl
* child_layer
= child
.get();
4824 root
->AddChild(child
.Pass());
4825 root_clip
->AddChild(root
.Pass());
4826 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4827 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4828 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4829 host_impl_
->active_tree()->DidBecomeActive();
4830 host_impl_
->SetViewportSize(surface_size
);
4833 gfx::Vector2d
scroll_delta(0, -10);
4834 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4835 host_impl_
->ScrollBegin(gfx::Point(),
4836 InputHandler::NON_BUBBLING_GESTURE
));
4837 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4838 EXPECT_TRUE(scroll_result
.did_scroll
);
4839 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4840 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4841 host_impl_
->ScrollEnd();
4843 // The next time we scroll we should only scroll the parent, but overscroll
4844 // should still not reach the root layer.
4845 scroll_delta
= gfx::Vector2d(0, -30);
4846 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4847 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4848 InputHandler::NON_BUBBLING_GESTURE
));
4849 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4850 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4851 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4852 EXPECT_TRUE(scroll_result
.did_scroll
);
4853 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4854 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4855 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4856 host_impl_
->ScrollEnd();
4858 // After scrolling the parent, another scroll on the opposite direction
4859 // should scroll the child.
4860 scroll_delta
= gfx::Vector2d(0, 70);
4861 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4862 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4863 InputHandler::NON_BUBBLING_GESTURE
));
4864 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4865 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4866 EXPECT_TRUE(scroll_result
.did_scroll
);
4867 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4868 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4869 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4870 host_impl_
->ScrollEnd();
4874 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4875 // When we try to scroll a non-scrollable child layer, the scroll delta
4876 // should be applied to one of its ancestors if possible. Overscroll should
4877 // be reflected only when it has bubbled up to the root scrolling layer.
4878 InputHandlerScrollResult scroll_result
;
4879 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4882 gfx::Vector2d
scroll_delta(0, 8);
4883 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4884 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4885 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4886 EXPECT_TRUE(scroll_result
.did_scroll
);
4887 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4888 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4889 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4890 EXPECT_TRUE(scroll_result
.did_scroll
);
4891 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4892 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4893 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4894 EXPECT_FALSE(scroll_result
.did_scroll
);
4895 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4896 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4897 host_impl_
->ScrollEnd();
4901 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4902 InputHandlerScrollResult scroll_result
;
4903 LayerTreeSettings settings
;
4904 CreateHostImpl(settings
, CreateOutputSurface());
4906 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4907 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4908 clip_layer
->SetBounds(gfx::Size(50, 50));
4909 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4910 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4912 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4914 // Even though the layer can't scroll the overscroll still happens.
4915 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4916 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4917 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4918 EXPECT_FALSE(scroll_result
.did_scroll
);
4919 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4920 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4923 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4924 InputHandlerScrollResult scroll_result
;
4925 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4929 // Edge glow effect should be applicable only upon reaching Edges
4930 // of the content. unnecessary glow effect calls shouldn't be
4931 // called while scrolling up without reaching the edge of the content.
4932 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4933 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4934 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4935 EXPECT_TRUE(scroll_result
.did_scroll
);
4936 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4937 EXPECT_EQ(gfx::Vector2dF().ToString(),
4938 host_impl_
->accumulated_root_overscroll().ToString());
4940 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4941 EXPECT_TRUE(scroll_result
.did_scroll
);
4942 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4943 EXPECT_EQ(gfx::Vector2dF().ToString(),
4944 host_impl_
->accumulated_root_overscroll().ToString());
4945 host_impl_
->ScrollEnd();
4946 // unusedrootDelta should be subtracted from applied delta so that
4947 // unwanted glow effect calls are not called.
4948 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4949 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4950 InputHandler::NON_BUBBLING_GESTURE
));
4951 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4952 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4953 EXPECT_TRUE(scroll_result
.did_scroll
);
4954 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4955 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4956 host_impl_
->accumulated_root_overscroll().ToString());
4959 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4960 EXPECT_FALSE(scroll_result
.did_scroll
);
4961 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4962 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4963 host_impl_
->accumulated_root_overscroll().ToString());
4964 host_impl_
->ScrollEnd();
4965 // TestCase to check kEpsilon, which prevents minute values to trigger
4966 // gloweffect without reaching edge.
4967 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4968 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4970 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4971 EXPECT_FALSE(scroll_result
.did_scroll
);
4972 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4973 EXPECT_EQ(gfx::Vector2dF().ToString(),
4974 host_impl_
->accumulated_root_overscroll().ToString());
4975 host_impl_
->ScrollEnd();
4979 class BlendStateCheckLayer
: public LayerImpl
{
4981 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4983 ResourceProvider
* resource_provider
) {
4984 return make_scoped_ptr(
4985 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4988 void AppendQuads(RenderPass
* render_pass
,
4989 AppendQuadsData
* append_quads_data
) override
{
4990 quads_appended_
= true;
4992 gfx::Rect opaque_rect
;
4993 if (contents_opaque())
4994 opaque_rect
= quad_rect_
;
4996 opaque_rect
= opaque_content_rect_
;
4997 gfx::Rect visible_quad_rect
= quad_rect_
;
4999 SharedQuadState
* shared_quad_state
=
5000 render_pass
->CreateAndAppendSharedQuadState();
5001 PopulateSharedQuadState(shared_quad_state
);
5003 TileDrawQuad
* test_blending_draw_quad
=
5004 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
5005 test_blending_draw_quad
->SetNew(shared_quad_state
,
5010 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
5014 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
5015 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
5016 EXPECT_EQ(has_render_surface_
, !!render_surface());
5019 void SetExpectation(bool blend
, bool has_render_surface
) {
5021 has_render_surface_
= has_render_surface
;
5022 quads_appended_
= false;
5025 bool quads_appended() const { return quads_appended_
; }
5027 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
5028 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
5029 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
5030 opaque_content_rect_
= rect
;
5034 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
5036 ResourceProvider
* resource_provider
)
5037 : LayerImpl(tree_impl
, id
),
5039 has_render_surface_(false),
5040 quads_appended_(false),
5041 quad_rect_(5, 5, 5, 5),
5042 quad_visible_rect_(5, 5, 5, 5),
5043 resource_id_(resource_provider
->CreateResource(
5046 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
5048 resource_provider
->AllocateForTesting(resource_id_
);
5049 SetBounds(gfx::Size(10, 10));
5050 SetDrawsContent(true);
5054 bool has_render_surface_
;
5055 bool quads_appended_
;
5056 gfx::Rect quad_rect_
;
5057 gfx::Rect opaque_content_rect_
;
5058 gfx::Rect quad_visible_rect_
;
5059 ResourceId resource_id_
;
5062 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
5064 scoped_ptr
<LayerImpl
> root
=
5065 LayerImpl::Create(host_impl_
->active_tree(), 1);
5066 root
->SetBounds(gfx::Size(10, 10));
5067 root
->SetDrawsContent(false);
5068 root
->SetHasRenderSurface(true);
5069 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5071 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5074 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5076 host_impl_
->resource_provider()));
5077 BlendStateCheckLayer
* layer1
=
5078 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
5079 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
5081 LayerTreeHostImpl::FrameData frame
;
5083 // Opaque layer, drawn without blending.
5084 layer1
->SetContentsOpaque(true);
5085 layer1
->SetExpectation(false, false);
5086 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5087 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5088 host_impl_
->DrawLayers(&frame
);
5089 EXPECT_TRUE(layer1
->quads_appended());
5090 host_impl_
->DidDrawAllLayers(frame
);
5092 // Layer with translucent content and painting, so drawn with blending.
5093 layer1
->SetContentsOpaque(false);
5094 layer1
->SetExpectation(true, false);
5095 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5096 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5097 host_impl_
->DrawLayers(&frame
);
5098 EXPECT_TRUE(layer1
->quads_appended());
5099 host_impl_
->DidDrawAllLayers(frame
);
5101 // Layer with translucent opacity, drawn with blending.
5102 layer1
->SetContentsOpaque(true);
5103 layer1
->SetOpacity(0.5f
);
5104 layer1
->SetExpectation(true, false);
5105 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5106 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5107 host_impl_
->DrawLayers(&frame
);
5108 EXPECT_TRUE(layer1
->quads_appended());
5109 host_impl_
->DidDrawAllLayers(frame
);
5111 // Layer with translucent opacity and painting, drawn with blending.
5112 layer1
->SetContentsOpaque(true);
5113 layer1
->SetOpacity(0.5f
);
5114 layer1
->SetExpectation(true, false);
5115 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5116 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5117 host_impl_
->DrawLayers(&frame
);
5118 EXPECT_TRUE(layer1
->quads_appended());
5119 host_impl_
->DidDrawAllLayers(frame
);
5122 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5124 host_impl_
->resource_provider()));
5125 BlendStateCheckLayer
* layer2
=
5126 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
5127 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
5129 // 2 opaque layers, drawn without blending.
5130 layer1
->SetContentsOpaque(true);
5131 layer1
->SetOpacity(1.f
);
5132 layer1
->SetExpectation(false, false);
5133 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5134 layer2
->SetContentsOpaque(true);
5135 layer2
->SetOpacity(1.f
);
5136 layer2
->SetExpectation(false, false);
5137 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5138 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5139 host_impl_
->DrawLayers(&frame
);
5140 EXPECT_TRUE(layer1
->quads_appended());
5141 EXPECT_TRUE(layer2
->quads_appended());
5142 host_impl_
->DidDrawAllLayers(frame
);
5144 // Parent layer with translucent content, drawn with blending.
5145 // Child layer with opaque content, drawn without blending.
5146 layer1
->SetContentsOpaque(false);
5147 layer1
->SetExpectation(true, false);
5148 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5149 layer2
->SetExpectation(false, false);
5150 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5151 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5152 host_impl_
->DrawLayers(&frame
);
5153 EXPECT_TRUE(layer1
->quads_appended());
5154 EXPECT_TRUE(layer2
->quads_appended());
5155 host_impl_
->DidDrawAllLayers(frame
);
5157 // Parent layer with translucent content but opaque painting, drawn without
5159 // Child layer with opaque content, drawn without blending.
5160 layer1
->SetContentsOpaque(true);
5161 layer1
->SetExpectation(false, false);
5162 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5163 layer2
->SetExpectation(false, false);
5164 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5165 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5166 host_impl_
->DrawLayers(&frame
);
5167 EXPECT_TRUE(layer1
->quads_appended());
5168 EXPECT_TRUE(layer2
->quads_appended());
5169 host_impl_
->DidDrawAllLayers(frame
);
5171 // Parent layer with translucent opacity and opaque content. Since it has a
5172 // drawing child, it's drawn to a render surface which carries the opacity,
5173 // so it's itself drawn without blending.
5174 // Child layer with opaque content, drawn without blending (parent surface
5175 // carries the inherited opacity).
5176 layer1
->SetContentsOpaque(true);
5177 layer1
->SetOpacity(0.5f
);
5178 layer1
->SetHasRenderSurface(true);
5179 layer1
->SetExpectation(false, true);
5180 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5181 layer2
->SetExpectation(false, false);
5182 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5183 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5184 host_impl_
->active_tree()->root_layer());
5185 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5186 host_impl_
->DrawLayers(&frame
);
5187 EXPECT_TRUE(layer1
->quads_appended());
5188 EXPECT_TRUE(layer2
->quads_appended());
5189 host_impl_
->DidDrawAllLayers(frame
);
5190 layer1
->SetHasRenderSurface(false);
5192 // Draw again, but with child non-opaque, to make sure
5193 // layer1 not culled.
5194 layer1
->SetContentsOpaque(true);
5195 layer1
->SetOpacity(1.f
);
5196 layer1
->SetExpectation(false, false);
5197 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5198 layer2
->SetContentsOpaque(true);
5199 layer2
->SetOpacity(0.5f
);
5200 layer2
->SetExpectation(true, false);
5201 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5202 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5203 host_impl_
->DrawLayers(&frame
);
5204 EXPECT_TRUE(layer1
->quads_appended());
5205 EXPECT_TRUE(layer2
->quads_appended());
5206 host_impl_
->DidDrawAllLayers(frame
);
5208 // A second way of making the child non-opaque.
5209 layer1
->SetContentsOpaque(true);
5210 layer1
->SetOpacity(1.f
);
5211 layer1
->SetExpectation(false, false);
5212 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5213 layer2
->SetContentsOpaque(false);
5214 layer2
->SetOpacity(1.f
);
5215 layer2
->SetExpectation(true, false);
5216 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5217 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5218 host_impl_
->DrawLayers(&frame
);
5219 EXPECT_TRUE(layer1
->quads_appended());
5220 EXPECT_TRUE(layer2
->quads_appended());
5221 host_impl_
->DidDrawAllLayers(frame
);
5223 // And when the layer says its not opaque but is painted opaque, it is not
5225 layer1
->SetContentsOpaque(true);
5226 layer1
->SetOpacity(1.f
);
5227 layer1
->SetExpectation(false, false);
5228 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5229 layer2
->SetContentsOpaque(true);
5230 layer2
->SetOpacity(1.f
);
5231 layer2
->SetExpectation(false, false);
5232 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5233 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5234 host_impl_
->DrawLayers(&frame
);
5235 EXPECT_TRUE(layer1
->quads_appended());
5236 EXPECT_TRUE(layer2
->quads_appended());
5237 host_impl_
->DidDrawAllLayers(frame
);
5239 // Layer with partially opaque contents, drawn with blending.
5240 layer1
->SetContentsOpaque(false);
5241 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5242 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5243 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5244 layer1
->SetExpectation(true, false);
5245 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5246 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5247 host_impl_
->DrawLayers(&frame
);
5248 EXPECT_TRUE(layer1
->quads_appended());
5249 host_impl_
->DidDrawAllLayers(frame
);
5251 // Layer with partially opaque contents partially culled, drawn with blending.
5252 layer1
->SetContentsOpaque(false);
5253 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5254 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5255 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5256 layer1
->SetExpectation(true, false);
5257 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5258 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5259 host_impl_
->DrawLayers(&frame
);
5260 EXPECT_TRUE(layer1
->quads_appended());
5261 host_impl_
->DidDrawAllLayers(frame
);
5263 // Layer with partially opaque contents culled, drawn with blending.
5264 layer1
->SetContentsOpaque(false);
5265 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5266 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5267 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5268 layer1
->SetExpectation(true, false);
5269 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5270 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5271 host_impl_
->DrawLayers(&frame
);
5272 EXPECT_TRUE(layer1
->quads_appended());
5273 host_impl_
->DidDrawAllLayers(frame
);
5275 // Layer with partially opaque contents and translucent contents culled, drawn
5276 // without blending.
5277 layer1
->SetContentsOpaque(false);
5278 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5279 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5280 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5281 layer1
->SetExpectation(false, false);
5282 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5283 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5284 host_impl_
->DrawLayers(&frame
);
5285 EXPECT_TRUE(layer1
->quads_appended());
5286 host_impl_
->DidDrawAllLayers(frame
);
5289 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
5291 LayerTreeHostImplViewportCoveredTest() :
5292 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
5294 did_activate_pending_tree_(false) {}
5296 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
5298 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5300 return FakeOutputSurface::Create3d();
5303 void SetupActiveTreeLayers() {
5304 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
5305 host_impl_
->active_tree()->SetRootLayer(
5306 LayerImpl::Create(host_impl_
->active_tree(), 1));
5307 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
5308 host_impl_
->active_tree()->root_layer()->AddChild(
5309 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5311 host_impl_
->resource_provider()));
5312 child_
= static_cast<BlendStateCheckLayer
*>(
5313 host_impl_
->active_tree()->root_layer()->children()[0]);
5314 child_
->SetExpectation(false, false);
5315 child_
->SetContentsOpaque(true);
5318 // Expect no gutter rects.
5319 void TestLayerCoversFullViewport() {
5320 gfx::Rect
layer_rect(viewport_size_
);
5321 child_
->SetPosition(layer_rect
.origin());
5322 child_
->SetBounds(layer_rect
.size());
5323 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5324 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5326 LayerTreeHostImpl::FrameData frame
;
5327 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5328 ASSERT_EQ(1u, frame
.render_passes
.size());
5330 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5331 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5332 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5334 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5335 host_impl_
->DidDrawAllLayers(frame
);
5338 // Expect fullscreen gutter rect.
5339 void TestEmptyLayer() {
5340 gfx::Rect
layer_rect(0, 0, 0, 0);
5341 child_
->SetPosition(layer_rect
.origin());
5342 child_
->SetBounds(layer_rect
.size());
5343 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5344 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5346 LayerTreeHostImpl::FrameData frame
;
5347 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5348 ASSERT_EQ(1u, frame
.render_passes
.size());
5350 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5351 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5352 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5354 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5355 host_impl_
->DidDrawAllLayers(frame
);
5358 // Expect four surrounding gutter rects.
5359 void TestLayerInMiddleOfViewport() {
5360 gfx::Rect
layer_rect(500, 500, 200, 200);
5361 child_
->SetPosition(layer_rect
.origin());
5362 child_
->SetBounds(layer_rect
.size());
5363 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5364 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5366 LayerTreeHostImpl::FrameData frame
;
5367 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5368 ASSERT_EQ(1u, frame
.render_passes
.size());
5370 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5371 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
5372 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5374 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5375 host_impl_
->DidDrawAllLayers(frame
);
5378 // Expect no gutter rects.
5379 void TestLayerIsLargerThanViewport() {
5380 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
5381 viewport_size_
.height() + 10);
5382 child_
->SetPosition(layer_rect
.origin());
5383 child_
->SetBounds(layer_rect
.size());
5384 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5385 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5387 LayerTreeHostImpl::FrameData frame
;
5388 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5389 ASSERT_EQ(1u, frame
.render_passes
.size());
5391 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5392 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5393 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5395 host_impl_
->DidDrawAllLayers(frame
);
5398 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
5400 void set_gutter_quad_material(DrawQuad::Material material
) {
5401 gutter_quad_material_
= material
;
5403 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
5404 gutter_texture_size_
= gutter_texture_size
;
5408 size_t CountGutterQuads(const QuadList
& quad_list
) {
5409 size_t num_gutter_quads
= 0;
5410 for (const auto& quad
: quad_list
) {
5411 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
5413 return num_gutter_quads
;
5416 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
5417 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5418 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
5421 // Make sure that the texture coordinates match their expectations.
5422 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
5423 for (const auto& quad
: quad_list
) {
5424 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
5426 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
5427 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
5428 gutter_texture_size_
, host_impl_
->device_scale_factor());
5429 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
5430 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
5431 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
5432 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
5434 texture_quad
->uv_bottom_right
.x(),
5435 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
5437 texture_quad
->uv_bottom_right
.y(),
5438 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
5442 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
5443 return gfx::ToRoundedSize(
5444 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
5447 DrawQuad::Material gutter_quad_material_
;
5448 gfx::Size gutter_texture_size_
;
5449 gfx::Size viewport_size_
;
5450 BlendStateCheckLayer
* child_
;
5451 bool did_activate_pending_tree_
;
5454 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
5455 viewport_size_
= gfx::Size(1000, 1000);
5457 bool always_draw
= false;
5458 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5460 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5461 SetupActiveTreeLayers();
5462 TestLayerCoversFullViewport();
5464 TestLayerInMiddleOfViewport();
5465 TestLayerIsLargerThanViewport();
5468 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
5469 viewport_size_
= gfx::Size(1000, 1000);
5471 bool always_draw
= false;
5472 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5474 host_impl_
->SetDeviceScaleFactor(2.f
);
5475 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5476 SetupActiveTreeLayers();
5477 TestLayerCoversFullViewport();
5479 TestLayerInMiddleOfViewport();
5480 TestLayerIsLargerThanViewport();
5483 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
5484 viewport_size_
= gfx::Size(1000, 1000);
5486 bool always_draw
= true;
5487 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5489 // Pending tree to force active_tree size invalid. Not used otherwise.
5490 host_impl_
->CreatePendingTree();
5491 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5492 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5494 SetupActiveTreeLayers();
5496 TestLayerInMiddleOfViewport();
5497 TestLayerIsLargerThanViewport();
5500 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5501 viewport_size_
= gfx::Size(1000, 1000);
5503 bool always_draw
= true;
5504 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5506 // Set larger viewport and activate it to active tree.
5507 host_impl_
->CreatePendingTree();
5508 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5509 viewport_size_
.height() + 100);
5510 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5511 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5512 host_impl_
->ActivateSyncTree();
5513 EXPECT_TRUE(did_activate_pending_tree_
);
5514 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5516 // Shrink pending tree viewport without activating.
5517 host_impl_
->CreatePendingTree();
5518 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5519 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5521 SetupActiveTreeLayers();
5523 TestLayerInMiddleOfViewport();
5524 TestLayerIsLargerThanViewport();
5527 class FakeDrawableLayerImpl
: public LayerImpl
{
5529 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5530 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5533 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5534 : LayerImpl(tree_impl
, id
) {}
5537 // Only reshape when we know we are going to draw. Otherwise, the reshape
5538 // can leave the window at the wrong size if we never draw and the proper
5539 // viewport size is never set.
5540 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5541 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5542 scoped_ptr
<OutputSurface
> output_surface(
5543 FakeOutputSurface::Create3d(provider
));
5544 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5546 scoped_ptr
<LayerImpl
> root
=
5547 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5548 root
->SetBounds(gfx::Size(10, 10));
5549 root
->SetDrawsContent(true);
5550 root
->SetHasRenderSurface(true);
5551 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5552 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5553 provider
->TestContext3d()->clear_reshape_called();
5555 LayerTreeHostImpl::FrameData frame
;
5556 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5557 host_impl_
->SetDeviceScaleFactor(1.f
);
5558 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5559 host_impl_
->DrawLayers(&frame
);
5560 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5561 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5562 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5563 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5564 host_impl_
->DidDrawAllLayers(frame
);
5565 provider
->TestContext3d()->clear_reshape_called();
5567 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5568 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5569 host_impl_
->DrawLayers(&frame
);
5570 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5571 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5572 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5573 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5574 host_impl_
->DidDrawAllLayers(frame
);
5575 provider
->TestContext3d()->clear_reshape_called();
5577 host_impl_
->SetDeviceScaleFactor(2.f
);
5578 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5579 host_impl_
->DrawLayers(&frame
);
5580 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5581 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5582 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5583 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5584 host_impl_
->DidDrawAllLayers(frame
);
5585 provider
->TestContext3d()->clear_reshape_called();
5588 // Make sure damage tracking propagates all the way to the graphics context,
5589 // where it should request to swap only the sub-buffer that is damaged.
5590 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5591 scoped_refptr
<TestContextProvider
> context_provider(
5592 TestContextProvider::Create());
5593 context_provider
->BindToCurrentThread();
5594 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5596 scoped_ptr
<FakeOutputSurface
> output_surface(
5597 FakeOutputSurface::Create3d(context_provider
));
5598 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5600 // This test creates its own LayerTreeHostImpl, so
5601 // that we can force partial swap enabled.
5602 LayerTreeSettings settings
;
5603 settings
.renderer_settings
.partial_swap_enabled
= true;
5604 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5605 LayerTreeHostImpl::Create(
5606 settings
, this, &proxy_
, &stats_instrumentation_
,
5607 &shared_bitmap_manager_
, NULL
, &task_graph_runner_
, 0);
5608 layer_tree_host_impl
->InitializeRenderer(output_surface
.get());
5609 layer_tree_host_impl
->WillBeginImplFrame(
5610 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5611 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5613 scoped_ptr
<LayerImpl
> root
=
5614 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5615 root
->SetHasRenderSurface(true);
5616 scoped_ptr
<LayerImpl
> child
=
5617 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5618 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5619 child
->SetBounds(gfx::Size(14, 15));
5620 child
->SetDrawsContent(true);
5621 root
->SetBounds(gfx::Size(500, 500));
5622 root
->SetDrawsContent(true);
5623 root
->AddChild(child
.Pass());
5624 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5626 LayerTreeHostImpl::FrameData frame
;
5628 // First frame, the entire screen should get swapped.
5629 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5630 layer_tree_host_impl
->DrawLayers(&frame
);
5631 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5632 layer_tree_host_impl
->SwapBuffers(frame
);
5633 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5634 EXPECT_EQ(expected_swap_rect
.ToString(),
5635 fake_output_surface
->last_swap_rect().ToString());
5637 // Second frame, only the damaged area should get swapped. Damage should be
5638 // the union of old and new child rects.
5639 // expected damage rect: gfx::Rect(26, 28);
5640 // expected swap rect: vertically flipped, with origin at bottom left corner.
5641 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5643 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5644 layer_tree_host_impl
->DrawLayers(&frame
);
5645 host_impl_
->DidDrawAllLayers(frame
);
5646 layer_tree_host_impl
->SwapBuffers(frame
);
5648 // Make sure that partial swap is constrained to the viewport dimensions
5649 // expected damage rect: gfx::Rect(500, 500);
5650 // expected swap rect: flipped damage rect, but also clamped to viewport
5651 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5652 EXPECT_EQ(expected_swap_rect
.ToString(),
5653 fake_output_surface
->last_swap_rect().ToString());
5655 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5656 // This will damage everything.
5657 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5659 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5660 layer_tree_host_impl
->DrawLayers(&frame
);
5661 host_impl_
->DidDrawAllLayers(frame
);
5662 layer_tree_host_impl
->SwapBuffers(frame
);
5664 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5665 EXPECT_EQ(expected_swap_rect
.ToString(),
5666 fake_output_surface
->last_swap_rect().ToString());
5669 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5670 scoped_ptr
<LayerImpl
> root
=
5671 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5672 scoped_ptr
<LayerImpl
> child
=
5673 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5674 child
->SetBounds(gfx::Size(10, 10));
5675 child
->SetDrawsContent(true);
5676 root
->SetBounds(gfx::Size(10, 10));
5677 root
->SetDrawsContent(true);
5678 root
->SetHasRenderSurface(true);
5679 root
->AddChild(child
.Pass());
5681 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5683 LayerTreeHostImpl::FrameData frame
;
5685 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5686 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5687 EXPECT_EQ(1u, frame
.render_passes
.size());
5688 host_impl_
->DidDrawAllLayers(frame
);
5691 class FakeLayerWithQuads
: public LayerImpl
{
5693 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5694 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5697 void AppendQuads(RenderPass
* render_pass
,
5698 AppendQuadsData
* append_quads_data
) override
{
5699 SharedQuadState
* shared_quad_state
=
5700 render_pass
->CreateAndAppendSharedQuadState();
5701 PopulateSharedQuadState(shared_quad_state
);
5703 SkColor gray
= SkColorSetRGB(100, 100, 100);
5704 gfx::Rect
quad_rect(bounds());
5705 gfx::Rect
visible_quad_rect(quad_rect
);
5706 SolidColorDrawQuad
* my_quad
=
5707 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5709 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5713 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5714 : LayerImpl(tree_impl
, id
) {}
5717 class MockContext
: public TestWebGraphicsContext3D
{
5719 MOCK_METHOD1(useProgram
, void(GLuint program
));
5720 MOCK_METHOD5(uniform4f
, void(GLint location
,
5725 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5727 GLboolean transpose
,
5728 const GLfloat
* value
));
5729 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5733 MOCK_METHOD1(enable
, void(GLenum cap
));
5734 MOCK_METHOD1(disable
, void(GLenum cap
));
5735 MOCK_METHOD4(scissor
, void(GLint x
,
5741 class MockContextHarness
{
5743 MockContext
* context_
;
5746 explicit MockContextHarness(MockContext
* context
)
5747 : context_(context
) {
5748 context_
->set_have_post_sub_buffer(true);
5750 // Catch "uninteresting" calls
5751 EXPECT_CALL(*context_
, useProgram(_
))
5754 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5757 // These are not asserted
5758 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5759 .WillRepeatedly(Return());
5761 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5762 .WillRepeatedly(Return());
5764 // Any un-sanctioned calls to enable() are OK
5765 EXPECT_CALL(*context_
, enable(_
))
5766 .WillRepeatedly(Return());
5768 // Any un-sanctioned calls to disable() are OK
5769 EXPECT_CALL(*context_
, disable(_
))
5770 .WillRepeatedly(Return());
5773 void MustDrawSolidQuad() {
5774 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5776 .RetiresOnSaturation();
5778 EXPECT_CALL(*context_
, useProgram(_
))
5780 .RetiresOnSaturation();
5783 void MustSetScissor(int x
, int y
, int width
, int height
) {
5784 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5785 .WillRepeatedly(Return());
5787 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5789 .WillRepeatedly(Return());
5792 void MustSetNoScissor() {
5793 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5794 .WillRepeatedly(Return());
5796 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5799 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5804 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5805 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5806 MockContext
* mock_context
= mock_context_owned
.get();
5807 MockContextHarness
harness(mock_context
);
5810 LayerTreeSettings settings
= DefaultSettings();
5811 settings
.renderer_settings
.partial_swap_enabled
= false;
5812 CreateHostImpl(settings
,
5813 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5814 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5816 // Without partial swap, and no clipping, no scissor is set.
5817 harness
.MustDrawSolidQuad();
5818 harness
.MustSetNoScissor();
5820 LayerTreeHostImpl::FrameData frame
;
5821 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5822 host_impl_
->DrawLayers(&frame
);
5823 host_impl_
->DidDrawAllLayers(frame
);
5825 Mock::VerifyAndClearExpectations(&mock_context
);
5827 // Without partial swap, but a layer does clip its subtree, one scissor is
5829 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5830 harness
.MustDrawSolidQuad();
5831 harness
.MustSetScissor(0, 0, 10, 10);
5833 LayerTreeHostImpl::FrameData frame
;
5834 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
5835 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5836 host_impl_
->DrawLayers(&frame
);
5837 host_impl_
->DidDrawAllLayers(frame
);
5839 Mock::VerifyAndClearExpectations(&mock_context
);
5842 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5843 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5844 MockContext
* mock_context
= context_owned
.get();
5845 MockContextHarness
harness(mock_context
);
5847 LayerTreeSettings settings
= DefaultSettings();
5848 settings
.renderer_settings
.partial_swap_enabled
= true;
5849 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5850 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5852 // The first frame is not a partially-swapped one. No scissor should be set.
5853 harness
.MustSetNoScissor();
5854 harness
.MustDrawSolidQuad();
5856 LayerTreeHostImpl::FrameData frame
;
5857 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5858 host_impl_
->DrawLayers(&frame
);
5859 host_impl_
->DidDrawAllLayers(frame
);
5861 Mock::VerifyAndClearExpectations(&mock_context
);
5863 // Damage a portion of the frame.
5864 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5865 gfx::Rect(0, 0, 2, 3));
5867 // The second frame will be partially-swapped (the y coordinates are flipped).
5868 harness
.MustSetScissor(0, 7, 2, 3);
5869 harness
.MustDrawSolidQuad();
5871 LayerTreeHostImpl::FrameData frame
;
5872 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5873 host_impl_
->DrawLayers(&frame
);
5874 host_impl_
->DidDrawAllLayers(frame
);
5876 Mock::VerifyAndClearExpectations(&mock_context
);
5879 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5881 LayerTreeHostImplClient
* client
,
5883 SharedBitmapManager
* manager
,
5884 TaskGraphRunner
* task_graph_runner
,
5885 RenderingStatsInstrumentation
* stats_instrumentation
,
5886 OutputSurface
* output_surface
) {
5887 LayerTreeSettings settings
;
5888 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5889 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5890 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
,
5891 manager
, nullptr, task_graph_runner
, 0);
5892 my_host_impl
->InitializeRenderer(output_surface
);
5893 my_host_impl
->WillBeginImplFrame(
5894 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5895 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5898 Layers are created as follows:
5900 +--------------------+
5904 | | +-------------------+
5906 | | +-------------------+
5911 +--------------------+
5913 Layers 1, 2 have render surfaces
5915 scoped_ptr
<LayerImpl
> root
=
5916 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5917 scoped_ptr
<LayerImpl
> child
=
5918 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5919 scoped_ptr
<LayerImpl
> grand_child
=
5920 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5922 gfx::Rect
root_rect(0, 0, 100, 100);
5923 gfx::Rect
child_rect(10, 10, 50, 50);
5924 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5926 root
->SetHasRenderSurface(true);
5927 root
->SetPosition(root_rect
.origin());
5928 root
->SetBounds(root_rect
.size());
5929 root
->draw_properties().visible_layer_rect
= root_rect
;
5930 root
->SetDrawsContent(false);
5931 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5933 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5934 child
->SetOpacity(0.5f
);
5935 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5936 child
->draw_properties().visible_layer_rect
= child_rect
;
5937 child
->SetDrawsContent(false);
5938 child
->SetHasRenderSurface(true);
5940 grand_child
->SetPosition(grand_child_rect
.origin());
5941 grand_child
->SetBounds(grand_child_rect
.size());
5942 grand_child
->draw_properties().visible_layer_rect
= grand_child_rect
;
5943 grand_child
->SetDrawsContent(true);
5945 child
->AddChild(grand_child
.Pass());
5946 root
->AddChild(child
.Pass());
5948 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5949 return my_host_impl
.Pass();
5952 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5953 TestSharedBitmapManager shared_bitmap_manager
;
5954 TestTaskGraphRunner task_graph_runner
;
5955 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5956 provider
->BindToCurrentThread();
5957 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5958 scoped_ptr
<OutputSurface
> output_surface(
5959 FakeOutputSurface::Create3d(provider
));
5960 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
= SetupLayersForOpacity(
5961 true, this, &proxy_
, &shared_bitmap_manager
, &task_graph_runner
,
5962 &stats_instrumentation_
, output_surface
.get());
5964 LayerTreeHostImpl::FrameData frame
;
5965 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5967 // Verify all quads have been computed
5968 ASSERT_EQ(2U, frame
.render_passes
.size());
5969 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5970 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5971 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5972 frame
.render_passes
[0]->quad_list
.front()->material
);
5973 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5974 frame
.render_passes
[1]->quad_list
.front()->material
);
5976 my_host_impl
->DrawLayers(&frame
);
5977 my_host_impl
->DidDrawAllLayers(frame
);
5981 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5982 TestSharedBitmapManager shared_bitmap_manager
;
5983 TestTaskGraphRunner task_graph_runner
;
5984 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5985 provider
->BindToCurrentThread();
5986 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5987 scoped_ptr
<OutputSurface
> output_surface(
5988 FakeOutputSurface::Create3d(provider
));
5989 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
= SetupLayersForOpacity(
5990 false, this, &proxy_
, &shared_bitmap_manager
, &task_graph_runner
,
5991 &stats_instrumentation_
, output_surface
.get());
5993 LayerTreeHostImpl::FrameData frame
;
5994 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5996 // Verify all quads have been computed
5997 ASSERT_EQ(2U, frame
.render_passes
.size());
5998 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5999 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
6000 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
6001 frame
.render_passes
[0]->quad_list
.front()->material
);
6002 EXPECT_EQ(DrawQuad::RENDER_PASS
,
6003 frame
.render_passes
[1]->quad_list
.front()->material
);
6005 my_host_impl
->DrawLayers(&frame
);
6006 my_host_impl
->DidDrawAllLayers(frame
);
6010 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
6011 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6012 TestWebGraphicsContext3D::Create();
6013 TestWebGraphicsContext3D
* context3d
= context
.get();
6014 scoped_ptr
<OutputSurface
> output_surface(
6015 FakeOutputSurface::Create3d(context
.Pass()));
6016 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6018 scoped_ptr
<LayerImpl
> root_layer
=
6019 LayerImpl::Create(host_impl_
->active_tree(), 1);
6020 root_layer
->SetBounds(gfx::Size(10, 10));
6021 root_layer
->SetHasRenderSurface(true);
6023 scoped_refptr
<VideoFrame
> softwareFrame
=
6024 media::VideoFrame::CreateColorFrame(
6025 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
6026 FakeVideoFrameProvider provider
;
6027 provider
.set_frame(softwareFrame
);
6028 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6029 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
6030 video_layer
->SetBounds(gfx::Size(10, 10));
6031 video_layer
->SetDrawsContent(true);
6032 root_layer
->AddChild(video_layer
.Pass());
6034 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
6035 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
6036 io_surface_layer
->SetBounds(gfx::Size(10, 10));
6037 io_surface_layer
->SetDrawsContent(true);
6038 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
6039 root_layer
->AddChild(io_surface_layer
.Pass());
6041 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
6043 EXPECT_EQ(0u, context3d
->NumTextures());
6045 LayerTreeHostImpl::FrameData frame
;
6046 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6047 host_impl_
->DrawLayers(&frame
);
6048 host_impl_
->DidDrawAllLayers(frame
);
6049 host_impl_
->SwapBuffers(frame
);
6051 EXPECT_GT(context3d
->NumTextures(), 0u);
6053 // Kill the layer tree.
6054 host_impl_
->active_tree()->SetRootLayer(
6055 LayerImpl::Create(host_impl_
->active_tree(), 100));
6056 // There should be no textures left in use after.
6057 EXPECT_EQ(0u, context3d
->NumTextures());
6060 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
6062 MOCK_METHOD1(useProgram
, void(GLuint program
));
6063 MOCK_METHOD4(drawElements
, void(GLenum mode
,
6069 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
6070 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
6071 new MockDrawQuadsToFillScreenContext
);
6072 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
6075 LayerTreeSettings settings
= DefaultSettings();
6076 settings
.renderer_settings
.partial_swap_enabled
= false;
6077 CreateHostImpl(settings
,
6078 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
6079 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6080 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
6082 // Verify one quad is drawn when transparent background set is not set.
6083 host_impl_
->active_tree()->set_has_transparent_background(false);
6084 EXPECT_CALL(*mock_context
, useProgram(_
))
6086 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
6088 LayerTreeHostImpl::FrameData frame
;
6089 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6090 host_impl_
->DrawLayers(&frame
);
6091 host_impl_
->DidDrawAllLayers(frame
);
6092 Mock::VerifyAndClearExpectations(&mock_context
);
6094 // Verify no quads are drawn when transparent background is set.
6095 host_impl_
->active_tree()->set_has_transparent_background(true);
6096 host_impl_
->SetFullRootLayerDamage();
6097 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6098 host_impl_
->DrawLayers(&frame
);
6099 host_impl_
->DidDrawAllLayers(frame
);
6100 Mock::VerifyAndClearExpectations(&mock_context
);
6103 class LayerTreeHostImplTestWithDelegatingRenderer
6104 : public LayerTreeHostImplTest
{
6106 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
6107 return FakeOutputSurface::CreateDelegating3d();
6110 void DrawFrameAndTestDamage(const gfx::Rect
& expected_damage
) {
6111 bool expect_to_draw
= !expected_damage
.IsEmpty();
6113 LayerTreeHostImpl::FrameData frame
;
6114 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6116 if (!expect_to_draw
) {
6117 // With no damage, we don't draw, and no quads are created.
6118 ASSERT_EQ(0u, frame
.render_passes
.size());
6120 ASSERT_EQ(1u, frame
.render_passes
.size());
6122 // Verify the damage rect for the root render pass.
6123 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
6124 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
6126 // Verify the root and child layers' quads are generated and not being
6128 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
6130 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
6131 gfx::Rect
expected_child_visible_rect(child
->bounds());
6132 EXPECT_EQ(expected_child_visible_rect
,
6133 root_render_pass
->quad_list
.front()->visible_rect
);
6135 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
6136 gfx::Rect
expected_root_visible_rect(root
->bounds());
6137 EXPECT_EQ(expected_root_visible_rect
,
6138 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
6141 host_impl_
->DrawLayers(&frame
);
6142 host_impl_
->DidDrawAllLayers(frame
);
6143 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
6147 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
6148 scoped_ptr
<SolidColorLayerImpl
> root
=
6149 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6150 root
->SetPosition(gfx::PointF());
6151 root
->SetBounds(gfx::Size(10, 10));
6152 root
->SetDrawsContent(true);
6153 root
->SetHasRenderSurface(true);
6155 // Child layer is in the bottom right corner.
6156 scoped_ptr
<SolidColorLayerImpl
> child
=
6157 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
6158 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
6159 child
->SetBounds(gfx::Size(1, 1));
6160 child
->SetDrawsContent(true);
6161 root
->AddChild(child
.Pass());
6163 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6165 // Draw a frame. In the first frame, the entire viewport should be damaged.
6166 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6167 DrawFrameAndTestDamage(full_frame_damage
);
6169 // The second frame has damage that doesn't touch the child layer. Its quads
6170 // should still be generated.
6171 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
6172 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
6173 DrawFrameAndTestDamage(small_damage
);
6175 // The third frame should have no damage, so no quads should be generated.
6176 gfx::Rect no_damage
;
6177 DrawFrameAndTestDamage(no_damage
);
6180 // TODO(reveman): Remove this test and the ability to prevent on demand raster
6181 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
6182 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
6183 LayerTreeSettings settings
;
6184 CreateHostImpl(settings
, CreateOutputSurface());
6185 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
6188 class FakeMaskLayerImpl
: public LayerImpl
{
6190 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
6192 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
6195 void GetContentsResourceId(ResourceId
* resource_id
,
6196 gfx::Size
* resource_size
) const override
{
6201 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
6202 : LayerImpl(tree_impl
, id
) {}
6205 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
6207 using GLRenderer::ShouldAntialiasQuad
;
6210 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
6211 // Due to precision issues (especially on Android), sometimes far
6212 // away quads can end up thinking they need AA.
6213 float device_scale_factor
= 4.f
/ 3.f
;
6214 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
6215 gfx::Size
root_size(2000, 1000);
6216 gfx::Size device_viewport_size
=
6217 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
6218 host_impl_
->SetViewportSize(device_viewport_size
);
6220 host_impl_
->CreatePendingTree();
6221 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
6224 scoped_ptr
<LayerImpl
> scoped_root
=
6225 LayerImpl::Create(host_impl_
->pending_tree(), 1);
6226 LayerImpl
* root
= scoped_root
.get();
6227 root
->SetHasRenderSurface(true);
6229 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
6231 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
6232 LayerImpl::Create(host_impl_
->pending_tree(), 2);
6233 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
6234 root
->AddChild(scoped_scrolling_layer
.Pass());
6236 gfx::Size
content_layer_bounds(100000, 100);
6237 gfx::Size
pile_tile_size(3000, 3000);
6238 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
6239 pile_tile_size
, content_layer_bounds
));
6241 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
6242 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
6244 LayerImpl
* content_layer
= scoped_content_layer
.get();
6245 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
6246 content_layer
->SetBounds(content_layer_bounds
);
6247 content_layer
->SetDrawsContent(true);
6249 root
->SetBounds(root_size
);
6251 gfx::ScrollOffset
scroll_offset(100000, 0);
6252 scrolling_layer
->SetScrollClipLayer(root
->id());
6253 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
6255 host_impl_
->ActivateSyncTree();
6257 bool update_lcd_text
= false;
6258 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
6259 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
6261 LayerTreeHostImpl::FrameData frame
;
6262 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6264 ASSERT_EQ(1u, frame
.render_passes
.size());
6265 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
6266 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
6268 bool clipped
= false, force_aa
= false;
6269 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
6270 quad
->shared_quad_state
->quad_to_target_transform
,
6271 gfx::QuadF(gfx::RectF(quad
->shared_quad_state
->visible_quad_layer_rect
)),
6273 EXPECT_FALSE(clipped
);
6275 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6276 device_layer_quad
, clipped
, force_aa
);
6277 EXPECT_FALSE(antialiased
);
6279 host_impl_
->DrawLayers(&frame
);
6280 host_impl_
->DidDrawAllLayers(frame
);
6284 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
6286 CompositorFrameMetadataTest()
6287 : swap_buffers_complete_(0) {}
6289 void DidSwapBuffersCompleteOnImplThread() override
{
6290 swap_buffers_complete_
++;
6293 int swap_buffers_complete_
;
6296 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
6297 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
6299 LayerTreeHostImpl::FrameData frame
;
6300 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6301 host_impl_
->DrawLayers(&frame
);
6302 host_impl_
->DidDrawAllLayers(frame
);
6304 CompositorFrameAck ack
;
6305 host_impl_
->ReclaimResources(&ack
);
6306 host_impl_
->DidSwapBuffersComplete();
6307 EXPECT_EQ(swap_buffers_complete_
, 1);
6310 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
6312 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6314 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
6316 return SoftwareOutputDevice::BeginPaint(damage_rect
);
6318 void EndPaint() override
{
6319 SoftwareOutputDevice::EndPaint();
6323 int frames_began_
, frames_ended_
;
6326 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
6327 // No main thread evictions in resourceless software mode.
6328 set_reduce_memory_result(false);
6329 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
6330 EXPECT_TRUE(CreateHostImpl(
6332 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
6333 host_impl_
->SetViewportSize(gfx::Size(50, 50));
6335 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6337 const gfx::Transform external_transform
;
6338 const gfx::Rect external_viewport
;
6339 const gfx::Rect external_clip
;
6340 const bool resourceless_software_draw
= true;
6341 host_impl_
->SetExternalDrawConstraints(external_transform
,
6346 resourceless_software_draw
);
6348 EXPECT_EQ(0, software_device
->frames_began_
);
6349 EXPECT_EQ(0, software_device
->frames_ended_
);
6353 EXPECT_EQ(1, software_device
->frames_began_
);
6354 EXPECT_EQ(1, software_device
->frames_ended_
);
6356 // Call another API method that is likely to hit nullptr in this mode.
6357 scoped_refptr
<base::trace_event::TracedValue
> state
=
6358 make_scoped_refptr(new base::trace_event::TracedValue());
6359 host_impl_
->ActivationStateAsValueInto(state
.get());
6362 TEST_F(LayerTreeHostImplTest
,
6363 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
6364 set_reduce_memory_result(false);
6365 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6366 FakeOutputSurface::CreateSoftware(
6367 make_scoped_ptr(new CountingSoftwareDevice
))));
6369 const gfx::Transform external_transform
;
6370 const gfx::Rect external_viewport
;
6371 const gfx::Rect external_clip
;
6372 const bool resourceless_software_draw
= true;
6373 host_impl_
->SetExternalDrawConstraints(external_transform
,
6378 resourceless_software_draw
);
6380 // SolidColorLayerImpl will be drawn.
6381 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
6382 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6384 // VideoLayerImpl will not be drawn.
6385 FakeVideoFrameProvider provider
;
6386 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6387 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
6388 video_layer
->SetBounds(gfx::Size(10, 10));
6389 video_layer
->SetDrawsContent(true);
6390 root_layer
->AddChild(video_layer
.Pass());
6391 SetupRootLayerImpl(root_layer
.Pass());
6393 LayerTreeHostImpl::FrameData frame
;
6394 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6395 host_impl_
->DrawLayers(&frame
);
6396 host_impl_
->DidDrawAllLayers(frame
);
6398 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
6399 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
6402 // Checks that we have a non-0 default allocation if we pass a context that
6403 // doesn't support memory management extensions.
6404 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
6405 LayerTreeSettings settings
;
6406 host_impl_
= LayerTreeHostImpl::Create(
6407 settings
, this, &proxy_
, &stats_instrumentation_
, &shared_bitmap_manager_
,
6408 &gpu_memory_buffer_manager_
, &task_graph_runner_
, 0);
6411 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create());
6412 host_impl_
->InitializeRenderer(output_surface_
.get());
6413 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
6416 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6417 ASSERT_TRUE(host_impl_
->active_tree());
6419 // RequiresHighResToDraw is set when new output surface is used.
6420 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6422 host_impl_
->ResetRequiresHighResToDraw();
6424 host_impl_
->SetVisible(false);
6425 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6426 host_impl_
->SetVisible(true);
6427 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6428 host_impl_
->SetVisible(false);
6429 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6431 host_impl_
->ResetRequiresHighResToDraw();
6433 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6434 host_impl_
->SetVisible(true);
6435 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6438 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6439 ASSERT_TRUE(host_impl_
->active_tree());
6440 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6442 // RequiresHighResToDraw is set when new output surface is used.
6443 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6445 host_impl_
->ResetRequiresHighResToDraw();
6447 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6448 host_impl_
->SetHasGpuRasterizationTrigger(false);
6449 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6450 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6451 host_impl_
->SetHasGpuRasterizationTrigger(true);
6452 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6453 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6454 host_impl_
->SetHasGpuRasterizationTrigger(false);
6455 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6456 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6458 host_impl_
->ResetRequiresHighResToDraw();
6460 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6461 host_impl_
->SetHasGpuRasterizationTrigger(true);
6462 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6463 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6466 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6468 void SetUp() override
{
6470 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_
,
6471 &shared_bitmap_manager_
, &task_graph_runner_
);
6472 host_impl_
.reset(fake_host_impl_
);
6473 output_surface_
= CreateOutputSurface();
6474 host_impl_
->InitializeRenderer(output_surface_
.get());
6475 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6478 FakeLayerTreeHostImpl
* fake_host_impl_
;
6481 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6482 fake_host_impl_
->DidModifyTilePriorities();
6483 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6484 fake_host_impl_
->SetVisible(false);
6485 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6488 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6489 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6490 TestWebGraphicsContext3D::Create();
6491 TestWebGraphicsContext3D
* context3d
= context
.get();
6492 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6493 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6495 EXPECT_EQ(0u, context3d
->NumTextures());
6497 UIResourceId ui_resource_id
= 1;
6498 bool is_opaque
= false;
6499 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6500 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6501 EXPECT_EQ(1u, context3d
->NumTextures());
6502 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6505 // Multiple requests with the same id is allowed. The previous texture is
6507 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6508 EXPECT_EQ(1u, context3d
->NumTextures());
6509 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6511 EXPECT_NE(id1
, id2
);
6513 // Deleting invalid UIResourceId is allowed and does not change state.
6514 host_impl_
->DeleteUIResource(-1);
6515 EXPECT_EQ(1u, context3d
->NumTextures());
6517 // Should return zero for invalid UIResourceId. Number of textures should
6519 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6520 EXPECT_EQ(1u, context3d
->NumTextures());
6522 host_impl_
->DeleteUIResource(ui_resource_id
);
6523 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6524 EXPECT_EQ(0u, context3d
->NumTextures());
6526 // Should not change state for multiple deletion on one UIResourceId
6527 host_impl_
->DeleteUIResource(ui_resource_id
);
6528 EXPECT_EQ(0u, context3d
->NumTextures());
6531 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6532 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6533 TestWebGraphicsContext3D::Create();
6534 TestWebGraphicsContext3D
* context3d
= context
.get();
6535 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6537 EXPECT_EQ(0u, context3d
->NumTextures());
6539 gfx::Size
size(4, 4);
6540 // SkImageInfo has no support for ETC1. The |info| below contains the right
6541 // total pixel size for the bitmap but not the right height and width. The
6542 // correct width/height are passed directly to UIResourceBitmap.
6544 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6545 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6546 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6547 pixel_ref
->setImmutable();
6548 UIResourceBitmap
bitmap(pixel_ref
, size
);
6549 UIResourceId ui_resource_id
= 1;
6550 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6551 EXPECT_EQ(1u, context3d
->NumTextures());
6552 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6556 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6559 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6560 scoped_refptr
<TestContextProvider
> context_provider
=
6561 TestContextProvider::Create();
6563 CreateHostImpl(DefaultSettings(),
6564 FakeOutputSurface::Create3d(context_provider
));
6566 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6568 ScopedPtrVector
<CopyOutputRequest
> requests
;
6569 requests
.push_back(CopyOutputRequest::CreateRequest(
6570 base::Bind(&ShutdownReleasesContext_Callback
)));
6572 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6574 LayerTreeHostImpl::FrameData frame
;
6575 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6576 host_impl_
->DrawLayers(&frame
);
6577 host_impl_
->DidDrawAllLayers(frame
);
6579 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6580 // texture in a texture mailbox.
6581 EXPECT_FALSE(context_provider
->HasOneRef());
6582 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6584 host_impl_
= nullptr;
6586 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6587 // released, and the texture deleted.
6588 EXPECT_TRUE(context_provider
->HasOneRef());
6589 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6592 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6593 // When flinging via touch, only the child should scroll (we should not
6595 gfx::Size
surface_size(10, 10);
6596 gfx::Size
content_size(20, 20);
6597 scoped_ptr
<LayerImpl
> root_clip
=
6598 LayerImpl::Create(host_impl_
->active_tree(), 3);
6599 root_clip
->SetHasRenderSurface(true);
6601 scoped_ptr
<LayerImpl
> root
=
6602 CreateScrollableLayer(1, content_size
, root_clip
.get());
6603 root
->SetIsContainerForFixedPositionLayers(true);
6604 scoped_ptr
<LayerImpl
> child
=
6605 CreateScrollableLayer(2, content_size
, root_clip
.get());
6607 root
->AddChild(child
.Pass());
6608 int root_id
= root
->id();
6609 root_clip
->AddChild(root
.Pass());
6611 host_impl_
->SetViewportSize(surface_size
);
6612 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6613 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6615 host_impl_
->active_tree()->DidBecomeActive();
6618 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6619 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6621 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6623 gfx::Vector2d
scroll_delta(0, 100);
6624 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6625 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6627 host_impl_
->ScrollEnd();
6629 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6630 host_impl_
->ProcessScrollDeltas();
6632 // Only the child should have scrolled.
6633 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6634 ExpectNone(*scroll_info
.get(), root_id
);
6638 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6639 // Scroll a child layer beyond its maximum scroll range and make sure the
6640 // the scroll doesn't bubble up to the parent layer.
6641 gfx::Size
surface_size(10, 10);
6642 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6643 root
->SetHasRenderSurface(true);
6644 scoped_ptr
<LayerImpl
> root_scrolling
=
6645 CreateScrollableLayer(2, surface_size
, root
.get());
6647 scoped_ptr
<LayerImpl
> grand_child
=
6648 CreateScrollableLayer(4, surface_size
, root
.get());
6649 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6651 scoped_ptr
<LayerImpl
> child
=
6652 CreateScrollableLayer(3, surface_size
, root
.get());
6653 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6654 child
->AddChild(grand_child
.Pass());
6656 root_scrolling
->AddChild(child
.Pass());
6657 root
->AddChild(root_scrolling
.Pass());
6658 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6659 host_impl_
->active_tree()->DidBecomeActive();
6660 host_impl_
->SetViewportSize(surface_size
);
6663 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6665 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6666 LayerImpl
* grand_child
= child
->children()[0];
6668 gfx::Vector2d
scroll_delta(0, -2);
6669 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6670 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6671 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6673 // The grand child should have scrolled up to its limit.
6674 scroll_info
= host_impl_
->ProcessScrollDeltas();
6675 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6677 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6678 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6680 // The child should have received the bubbled delta, but the locked
6681 // scrolling layer should remain set as the grand child.
6682 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6683 scroll_info
= host_impl_
->ProcessScrollDeltas();
6684 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6686 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6687 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(), scroll_delta
));
6688 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6690 // The first |ScrollBy| after the fling should re-lock the scrolling
6691 // layer to the first layer that scrolled, which is the child.
6692 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6693 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6694 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6696 // The child should have scrolled up to its limit.
6697 scroll_info
= host_impl_
->ProcessScrollDeltas();
6698 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6700 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6701 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(),
6702 scroll_delta
+ scroll_delta
));
6704 // As the locked layer is at it's limit, no further scrolling can occur.
6705 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6706 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6707 host_impl_
->ScrollEnd();
6711 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6712 // When flinging via wheel, the root should eventually scroll (we should
6714 gfx::Size
surface_size(10, 10);
6715 gfx::Size
content_size(20, 20);
6716 scoped_ptr
<LayerImpl
> root_clip
=
6717 LayerImpl::Create(host_impl_
->active_tree(), 3);
6718 root_clip
->SetHasRenderSurface(true);
6719 scoped_ptr
<LayerImpl
> root_scroll
=
6720 CreateScrollableLayer(1, content_size
, root_clip
.get());
6721 int root_scroll_id
= root_scroll
->id();
6722 scoped_ptr
<LayerImpl
> child
=
6723 CreateScrollableLayer(2, content_size
, root_clip
.get());
6725 root_scroll
->AddChild(child
.Pass());
6726 root_clip
->AddChild(root_scroll
.Pass());
6728 host_impl_
->SetViewportSize(surface_size
);
6729 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6730 host_impl_
->active_tree()->DidBecomeActive();
6733 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6734 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6736 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6738 gfx::Vector2d
scroll_delta(0, 100);
6739 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6740 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6742 host_impl_
->ScrollEnd();
6744 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6745 host_impl_
->ProcessScrollDeltas();
6747 // The root should have scrolled.
6748 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6749 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll_id
,
6750 gfx::Vector2d(0, 10)));
6754 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6755 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6756 // we should return SCROLL_UNKNOWN.
6757 gfx::Size
content_size(100, 100);
6758 SetupScrollAndContentsLayers(content_size
);
6760 int scroll_layer_id
= 2;
6761 LayerImpl
* scroll_layer
=
6762 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6763 scroll_layer
->SetDrawsContent(true);
6765 int page_scale_layer_id
= 5;
6766 LayerImpl
* page_scale_layer
=
6767 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6769 int occluder_layer_id
= 6;
6770 scoped_ptr
<LayerImpl
> occluder_layer
=
6771 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6772 occluder_layer
->SetDrawsContent(true);
6773 occluder_layer
->SetBounds(content_size
);
6774 occluder_layer
->SetPosition(gfx::PointF());
6776 // The parent of the occluder is *above* the scroller.
6777 page_scale_layer
->AddChild(occluder_layer
.Pass());
6781 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6782 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6785 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6786 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6787 // is not the first scroller we encounter when walking up from the layer, we
6788 // should also return SCROLL_UNKNOWN.
6789 gfx::Size
content_size(100, 100);
6790 SetupScrollAndContentsLayers(content_size
);
6792 int scroll_layer_id
= 2;
6793 LayerImpl
* scroll_layer
=
6794 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6795 scroll_layer
->SetDrawsContent(true);
6797 int occluder_layer_id
= 6;
6798 scoped_ptr
<LayerImpl
> occluder_layer
=
6799 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6800 occluder_layer
->SetDrawsContent(true);
6801 occluder_layer
->SetBounds(content_size
);
6802 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6804 int child_scroll_clip_layer_id
= 7;
6805 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6806 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6808 int child_scroll_layer_id
= 8;
6809 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6810 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6812 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6814 child_scroll
->AddChild(occluder_layer
.Pass());
6815 scroll_layer
->AddChild(child_scroll
.Pass());
6819 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6820 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6823 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6824 gfx::Size
content_size(100, 100);
6825 SetupScrollAndContentsLayers(content_size
);
6827 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6829 int scroll_layer_id
= 2;
6830 LayerImpl
* scroll_layer
=
6831 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6833 int child_scroll_layer_id
= 7;
6834 scoped_ptr
<LayerImpl
> child_scroll
=
6835 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6836 child_scroll
->SetDrawsContent(false);
6838 scroll_layer
->AddChild(child_scroll
.Pass());
6842 // We should not have scrolled |child_scroll| even though we technically "hit"
6843 // it. The reason for this is that if the scrolling the scroll would not move
6844 // any layer that is a drawn RSLL member, then we can ignore the hit.
6846 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6847 // started scrolling the inner viewport.
6848 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6849 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6851 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6854 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6855 gfx::Size
content_size(100, 100);
6856 SetupScrollAndContentsLayers(content_size
);
6858 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6859 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6861 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6862 CreateScrollableLayer(7, content_size
, root
);
6863 invisible_scroll_layer
->SetDrawsContent(false);
6865 scoped_ptr
<LayerImpl
> child_layer
=
6866 LayerImpl::Create(host_impl_
->active_tree(), 8);
6867 child_layer
->SetDrawsContent(false);
6869 scoped_ptr
<LayerImpl
> grand_child_layer
=
6870 LayerImpl::Create(host_impl_
->active_tree(), 9);
6871 grand_child_layer
->SetDrawsContent(true);
6872 grand_child_layer
->SetBounds(content_size
);
6873 // Move the grand child so it's not hit by our test point.
6874 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6876 child_layer
->AddChild(grand_child_layer
.Pass());
6877 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6878 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6882 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6883 // a descendant which is a drawn RSLL member.
6884 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6885 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6887 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6890 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6891 // This test case is very similar to the one above with one key difference:
6892 // the invisible scroller has a scroll child that is indeed draw contents.
6893 // If we attempt to initiate a gesture scroll off of the visible scroll child
6894 // we should still start the scroll child.
6895 gfx::Size
content_size(100, 100);
6896 SetupScrollAndContentsLayers(content_size
);
6898 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6900 int scroll_layer_id
= 2;
6901 LayerImpl
* scroll_layer
=
6902 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6904 int scroll_child_id
= 6;
6905 scoped_ptr
<LayerImpl
> scroll_child
=
6906 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6907 scroll_child
->SetDrawsContent(true);
6908 scroll_child
->SetBounds(content_size
);
6909 // Move the scroll child so it's not hit by our test point.
6910 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6912 int invisible_scroll_layer_id
= 7;
6913 scoped_ptr
<LayerImpl
> invisible_scroll
=
6914 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6915 invisible_scroll
->SetDrawsContent(false);
6917 int container_id
= 8;
6918 scoped_ptr
<LayerImpl
> container
=
6919 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6921 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6922 scroll_children
->insert(scroll_child
.get());
6923 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6925 scroll_child
->SetScrollParent(invisible_scroll
.get());
6927 container
->AddChild(invisible_scroll
.Pass());
6928 container
->AddChild(scroll_child
.Pass());
6930 scroll_layer
->AddChild(container
.Pass());
6934 // We should have scrolled |child_scroll| even though it is invisible.
6935 // The reason for this is that if the scrolling the scroll would move a layer
6936 // that is a drawn RSLL member, then we should accept this hit.
6937 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6938 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6940 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6943 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6944 // to CompositorFrameMetadata after SwapBuffers();
6945 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6946 scoped_ptr
<SolidColorLayerImpl
> root
=
6947 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6948 root
->SetPosition(gfx::PointF());
6949 root
->SetBounds(gfx::Size(10, 10));
6950 root
->SetDrawsContent(true);
6951 root
->SetHasRenderSurface(true);
6953 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6955 FakeOutputSurface
* fake_output_surface
=
6956 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6958 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6959 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6960 EXPECT_TRUE(metadata_latency_before
.empty());
6962 ui::LatencyInfo latency_info
;
6963 latency_info
.AddLatencyNumber(
6964 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6965 scoped_ptr
<SwapPromise
> swap_promise(
6966 new LatencyInfoSwapPromise(latency_info
));
6967 host_impl_
->active_tree()->QueuePinnedSwapPromise(swap_promise
.Pass());
6968 host_impl_
->SetNeedsRedraw();
6970 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6971 LayerTreeHostImpl::FrameData frame
;
6972 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6973 host_impl_
->DrawLayers(&frame
);
6974 host_impl_
->DidDrawAllLayers(frame
);
6975 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6977 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6978 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6979 EXPECT_EQ(1u, metadata_latency_after
.size());
6980 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6981 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6984 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6985 int root_layer_id
= 1;
6986 scoped_ptr
<SolidColorLayerImpl
> root
=
6987 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6988 root
->SetPosition(gfx::PointF());
6989 root
->SetBounds(gfx::Size(10, 10));
6990 root
->SetDrawsContent(true);
6991 root
->SetHasRenderSurface(true);
6993 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6995 // Ensure the default frame selection bounds are empty.
6996 FakeOutputSurface
* fake_output_surface
=
6997 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6998 const ViewportSelection
& selection_before
=
6999 fake_output_surface
->last_sent_frame().metadata
.selection
;
7000 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
7001 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
7003 // Plumb the layer-local selection bounds.
7004 gfx::PointF
selection_top(5, 0);
7005 gfx::PointF
selection_bottom(5, 5);
7006 LayerSelection selection
;
7007 selection
.start
.type
= SELECTION_BOUND_CENTER
;
7008 selection
.start
.layer_id
= root_layer_id
;
7009 selection
.start
.edge_bottom
= selection_bottom
;
7010 selection
.start
.edge_top
= selection_top
;
7011 selection
.end
= selection
.start
;
7012 host_impl_
->active_tree()->RegisterSelection(selection
);
7014 // Trigger a draw-swap sequence.
7015 host_impl_
->SetNeedsRedraw();
7017 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
7018 LayerTreeHostImpl::FrameData frame
;
7019 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
7020 host_impl_
->DrawLayers(&frame
);
7021 host_impl_
->DidDrawAllLayers(frame
);
7022 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
7024 // Ensure the selection bounds have propagated to the frame metadata.
7025 const ViewportSelection
& selection_after
=
7026 fake_output_surface
->last_sent_frame().metadata
.selection
;
7027 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
7028 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
7029 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
7030 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
7031 EXPECT_TRUE(selection_after
.start
.visible
);
7032 EXPECT_TRUE(selection_after
.start
.visible
);
7035 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
7037 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
7038 LayerTreeHostImpl
* layer_tree_host_impl
,
7039 int* set_needs_commit_count
,
7040 int* set_needs_redraw_count
,
7041 int* forward_to_main_count
)
7042 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
7043 set_needs_commit_count_(set_needs_commit_count
),
7044 set_needs_redraw_count_(set_needs_redraw_count
),
7045 forward_to_main_count_(forward_to_main_count
) {}
7047 ~SimpleSwapPromiseMonitor() override
{}
7049 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
7051 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
7053 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
7054 (*forward_to_main_count_
)++;
7058 int* set_needs_commit_count_
;
7059 int* set_needs_redraw_count_
;
7060 int* forward_to_main_count_
;
7063 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
7064 int set_needs_commit_count
= 0;
7065 int set_needs_redraw_count
= 0;
7066 int forward_to_main_count
= 0;
7069 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7070 new SimpleSwapPromiseMonitor(NULL
,
7072 &set_needs_commit_count
,
7073 &set_needs_redraw_count
,
7074 &forward_to_main_count
));
7075 host_impl_
->SetNeedsRedraw();
7076 EXPECT_EQ(0, set_needs_commit_count
);
7077 EXPECT_EQ(1, set_needs_redraw_count
);
7078 EXPECT_EQ(0, forward_to_main_count
);
7081 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7083 host_impl_
->SetNeedsRedraw();
7084 EXPECT_EQ(0, set_needs_commit_count
);
7085 EXPECT_EQ(1, set_needs_redraw_count
);
7086 EXPECT_EQ(0, forward_to_main_count
);
7089 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7090 new SimpleSwapPromiseMonitor(NULL
,
7092 &set_needs_commit_count
,
7093 &set_needs_redraw_count
,
7094 &forward_to_main_count
));
7095 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
7096 EXPECT_EQ(0, set_needs_commit_count
);
7097 EXPECT_EQ(2, set_needs_redraw_count
);
7098 EXPECT_EQ(0, forward_to_main_count
);
7102 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7103 new SimpleSwapPromiseMonitor(NULL
,
7105 &set_needs_commit_count
,
7106 &set_needs_redraw_count
,
7107 &forward_to_main_count
));
7108 // Empty damage rect won't signal the monitor.
7109 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
7110 EXPECT_EQ(0, set_needs_commit_count
);
7111 EXPECT_EQ(2, set_needs_redraw_count
);
7112 EXPECT_EQ(0, forward_to_main_count
);
7116 set_needs_commit_count
= 0;
7117 set_needs_redraw_count
= 0;
7118 forward_to_main_count
= 0;
7119 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7120 new SimpleSwapPromiseMonitor(NULL
,
7122 &set_needs_commit_count
,
7123 &set_needs_redraw_count
,
7124 &forward_to_main_count
));
7125 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7127 // Scrolling normally should not trigger any forwarding.
7128 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7129 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7131 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7132 host_impl_
->ScrollEnd();
7134 EXPECT_EQ(0, set_needs_commit_count
);
7135 EXPECT_EQ(1, set_needs_redraw_count
);
7136 EXPECT_EQ(0, forward_to_main_count
);
7138 // Scrolling with a scroll handler should defer the swap to the main
7140 scroll_layer
->SetHaveScrollEventHandlers(true);
7141 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7142 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7144 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7145 host_impl_
->ScrollEnd();
7147 EXPECT_EQ(0, set_needs_commit_count
);
7148 EXPECT_EQ(2, set_needs_redraw_count
);
7149 EXPECT_EQ(1, forward_to_main_count
);
7153 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
7155 void SetUp() override
{
7156 LayerTreeSettings settings
= DefaultSettings();
7157 CreateHostImpl(settings
, CreateOutputSurface());
7158 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
7159 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
7160 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
7164 static const int top_controls_height_
;
7167 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
7169 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
7170 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7171 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7172 BeginFrameArgs begin_frame_args
=
7173 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7174 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7175 host_impl_
->Animate();
7176 EXPECT_FALSE(did_request_redraw_
);
7177 host_impl_
->DidFinishImplFrame();
7180 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
7181 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7182 EXPECT_FALSE(did_request_redraw_
);
7183 host_impl_
->CreatePendingTree();
7184 host_impl_
->sync_tree()->set_top_controls_height(100);
7185 host_impl_
->ActivateSyncTree();
7186 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
7189 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7190 TopControlsStayFullyVisibleOnHeightChange
) {
7191 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7192 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7194 host_impl_
->CreatePendingTree();
7195 host_impl_
->sync_tree()->set_top_controls_height(0);
7196 host_impl_
->ActivateSyncTree();
7197 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7199 host_impl_
->CreatePendingTree();
7200 host_impl_
->sync_tree()->set_top_controls_height(50);
7201 host_impl_
->ActivateSyncTree();
7202 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7205 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
7206 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7207 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7208 host_impl_
->DidChangeTopControlsPosition();
7209 EXPECT_TRUE(did_request_animate_
);
7210 EXPECT_TRUE(did_request_redraw_
);
7213 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
7214 InputHandlerScrollResult result
;
7215 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7216 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7217 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7218 BOTH
, SHOWN
, false);
7221 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7222 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7223 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7224 EXPECT_EQ(gfx::Vector2dF().ToString(),
7225 scroll_layer
->CurrentScrollOffset().ToString());
7227 // Scroll just the top controls and verify that the scroll succeeds.
7228 const float residue
= 10;
7229 float offset
= top_controls_height_
- residue
;
7230 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7231 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7232 EXPECT_TRUE(result
.did_scroll
);
7233 EXPECT_FLOAT_EQ(-offset
,
7234 host_impl_
->top_controls_manager()->ControlsTopOffset());
7235 EXPECT_EQ(gfx::Vector2dF().ToString(),
7236 scroll_layer
->CurrentScrollOffset().ToString());
7238 // Scroll across the boundary
7239 const float content_scroll
= 20;
7240 offset
= residue
+ content_scroll
;
7241 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7242 EXPECT_TRUE(result
.did_scroll
);
7243 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7244 EXPECT_EQ(-top_controls_height_
,
7245 host_impl_
->top_controls_manager()->ControlsTopOffset());
7246 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
7247 scroll_layer
->CurrentScrollOffset().ToString());
7249 // Now scroll back to the top of the content
7250 offset
= -content_scroll
;
7251 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7252 EXPECT_TRUE(result
.did_scroll
);
7253 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7254 EXPECT_EQ(-top_controls_height_
,
7255 host_impl_
->top_controls_manager()->ControlsTopOffset());
7256 EXPECT_EQ(gfx::Vector2dF().ToString(),
7257 scroll_layer
->CurrentScrollOffset().ToString());
7259 // And scroll the top controls completely into view
7260 offset
= -top_controls_height_
;
7261 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7262 EXPECT_TRUE(result
.did_scroll
);
7263 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7264 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7265 EXPECT_EQ(gfx::Vector2dF().ToString(),
7266 scroll_layer
->CurrentScrollOffset().ToString());
7268 // And attempt to scroll past the end
7269 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7270 EXPECT_FALSE(result
.did_scroll
);
7271 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, -50));
7272 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7273 EXPECT_EQ(gfx::Vector2dF().ToString(),
7274 scroll_layer
->CurrentScrollOffset().ToString());
7276 host_impl_
->ScrollEnd();
7279 TEST_F(LayerTreeHostImplWithTopControlsTest
, WheelUnhandledByTopControls
) {
7280 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7281 host_impl_
->SetViewportSize(gfx::Size(50, 100));
7282 host_impl_
->active_tree()->set_top_controls_shrink_blink_size(true);
7283 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7287 LayerImpl
* viewport_layer
= host_impl_
->InnerViewportScrollLayer();
7289 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7290 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7291 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7292 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer
->CurrentScrollOffset());
7294 // Wheel scrolls should not affect the top controls, and should pass
7295 // directly through to the viewport.
7296 const float delta
= top_controls_height_
;
7298 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7299 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7300 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
),
7301 viewport_layer
->CurrentScrollOffset());
7304 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7305 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7306 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
* 2),
7307 viewport_layer
->CurrentScrollOffset());
7310 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
7311 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7312 host_impl_
->SetViewportSize(gfx::Size(100, 200));
7313 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7314 BOTH
, SHOWN
, false);
7317 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7318 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7319 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7320 EXPECT_EQ(gfx::Vector2dF().ToString(),
7321 scroll_layer
->CurrentScrollOffset().ToString());
7323 // Scroll the top controls partially.
7324 const float residue
= 35;
7325 float offset
= top_controls_height_
- residue
;
7327 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7328 EXPECT_FLOAT_EQ(-offset
,
7329 host_impl_
->top_controls_manager()->ControlsTopOffset());
7330 EXPECT_EQ(gfx::Vector2dF().ToString(),
7331 scroll_layer
->CurrentScrollOffset().ToString());
7333 did_request_redraw_
= false;
7334 did_request_animate_
= false;
7335 did_request_commit_
= false;
7337 // End the scroll while the controls are still offset from their limit.
7338 host_impl_
->ScrollEnd();
7339 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7340 EXPECT_TRUE(did_request_animate_
);
7341 EXPECT_TRUE(did_request_redraw_
);
7342 EXPECT_FALSE(did_request_commit_
);
7344 // The top controls should properly animate until finished, despite the scroll
7345 // offset being at the origin.
7346 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7347 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7348 while (did_request_animate_
) {
7349 did_request_redraw_
= false;
7350 did_request_animate_
= false;
7351 did_request_commit_
= false;
7354 host_impl_
->top_controls_manager()->ControlsTopOffset();
7356 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7357 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7358 host_impl_
->Animate();
7359 EXPECT_EQ(gfx::Vector2dF().ToString(),
7360 scroll_layer
->CurrentScrollOffset().ToString());
7363 host_impl_
->top_controls_manager()->ControlsTopOffset();
7365 // No commit is needed as the controls are animating the content offset,
7366 // not the scroll offset.
7367 EXPECT_FALSE(did_request_commit_
);
7369 if (new_offset
!= old_offset
)
7370 EXPECT_TRUE(did_request_redraw_
);
7372 if (new_offset
!= 0) {
7373 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
7374 EXPECT_TRUE(did_request_animate_
);
7376 host_impl_
->DidFinishImplFrame();
7378 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7381 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
7382 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7383 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7384 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7385 BOTH
, SHOWN
, false);
7386 float initial_scroll_offset
= 50;
7387 scroll_layer
->PushScrollOffsetFromMainThread(
7388 gfx::ScrollOffset(0, initial_scroll_offset
));
7391 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7392 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7393 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7394 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7395 scroll_layer
->CurrentScrollOffset().ToString());
7397 // Scroll the top controls partially.
7398 const float residue
= 15;
7399 float offset
= top_controls_height_
- residue
;
7401 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7402 EXPECT_FLOAT_EQ(-offset
,
7403 host_impl_
->top_controls_manager()->ControlsTopOffset());
7404 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7405 scroll_layer
->CurrentScrollOffset().ToString());
7407 did_request_redraw_
= false;
7408 did_request_animate_
= false;
7409 did_request_commit_
= false;
7411 // End the scroll while the controls are still offset from the limit.
7412 host_impl_
->ScrollEnd();
7413 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7414 EXPECT_TRUE(did_request_animate_
);
7415 EXPECT_TRUE(did_request_redraw_
);
7416 EXPECT_FALSE(did_request_commit_
);
7418 // Animate the top controls to the limit.
7419 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7420 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7421 while (did_request_animate_
) {
7422 did_request_redraw_
= false;
7423 did_request_animate_
= false;
7424 did_request_commit_
= false;
7427 host_impl_
->top_controls_manager()->ControlsTopOffset();
7429 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7430 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7431 host_impl_
->Animate();
7434 host_impl_
->top_controls_manager()->ControlsTopOffset();
7436 if (new_offset
!= old_offset
) {
7437 EXPECT_TRUE(did_request_redraw_
);
7438 EXPECT_TRUE(did_request_commit_
);
7440 host_impl_
->DidFinishImplFrame();
7442 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7443 EXPECT_EQ(-top_controls_height_
,
7444 host_impl_
->top_controls_manager()->ControlsTopOffset());
7447 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7448 TopControlsAnimationAfterMainThreadFlingStopped
) {
7449 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7450 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7451 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7453 float initial_scroll_offset
= 50;
7454 scroll_layer
->PushScrollOffsetFromMainThread(
7455 gfx::ScrollOffset(0, initial_scroll_offset
));
7458 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7459 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7460 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7461 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7462 scroll_layer
->CurrentScrollOffset().ToString());
7464 // Scroll the top controls partially.
7465 const float residue
= 15;
7466 float offset
= top_controls_height_
- residue
;
7468 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7469 EXPECT_FLOAT_EQ(-offset
,
7470 host_impl_
->top_controls_manager()->ControlsTopOffset());
7471 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7472 scroll_layer
->CurrentScrollOffset().ToString());
7474 did_request_redraw_
= false;
7475 did_request_animate_
= false;
7476 did_request_commit_
= false;
7478 // End the fling while the controls are still offset from the limit.
7479 host_impl_
->MainThreadHasStoppedFlinging();
7480 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7481 EXPECT_TRUE(did_request_animate_
);
7482 EXPECT_TRUE(did_request_redraw_
);
7483 EXPECT_FALSE(did_request_commit_
);
7485 // Animate the top controls to the limit.
7486 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7487 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7488 while (did_request_animate_
) {
7489 did_request_redraw_
= false;
7490 did_request_animate_
= false;
7491 did_request_commit_
= false;
7493 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7495 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7496 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7497 host_impl_
->Animate();
7499 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7501 if (new_offset
!= old_offset
) {
7502 EXPECT_TRUE(did_request_redraw_
);
7503 EXPECT_TRUE(did_request_commit_
);
7505 host_impl_
->DidFinishImplFrame();
7507 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7508 EXPECT_EQ(-top_controls_height_
,
7509 host_impl_
->top_controls_manager()->ControlsTopOffset());
7512 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7513 TopControlsScrollDeltaInOverScroll
) {
7514 // Verifies that the overscroll delta should not have accumulated in
7515 // the top controls if we do a hide and show without releasing finger.
7517 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7518 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7519 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7523 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7524 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7525 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7529 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7530 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7531 EXPECT_EQ(gfx::Vector2dF().ToString(),
7532 scroll_layer
->CurrentScrollOffset().ToString());
7535 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7536 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7537 scroll_layer
->CurrentScrollOffset().ToString());
7540 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7542 // Should have fully scrolled
7543 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7544 scroll_layer
->CurrentScrollOffset().ToString());
7546 float overscrollamount
= 10;
7548 // Overscroll the content
7550 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7552 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7553 scroll_layer
->CurrentScrollOffset().ToString());
7554 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7555 host_impl_
->accumulated_root_overscroll().ToString());
7557 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7559 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7560 scroll_layer
->CurrentScrollOffset().ToString());
7561 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7564 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7565 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7566 scroll_layer
->CurrentScrollOffset().ToString());
7568 // Top controls should be fully visible
7569 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7571 host_impl_
->ScrollEnd();
7574 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7576 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7577 const gfx::Size
& outer_viewport
,
7578 const gfx::Size
& inner_viewport
) {
7579 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7580 const int kOuterViewportClipLayerId
= 6;
7581 const int kOuterViewportScrollLayerId
= 7;
7582 const int kInnerViewportScrollLayerId
= 2;
7583 const int kInnerViewportClipLayerId
= 4;
7584 const int kPageScaleLayerId
= 5;
7586 scoped_ptr
<LayerImpl
> inner_scroll
=
7587 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7588 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7589 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7591 scoped_ptr
<LayerImpl
> inner_clip
=
7592 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7593 inner_clip
->SetBounds(inner_viewport
);
7595 scoped_ptr
<LayerImpl
> page_scale
=
7596 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7598 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7599 inner_scroll
->SetBounds(outer_viewport
);
7600 inner_scroll
->SetPosition(gfx::PointF());
7602 scoped_ptr
<LayerImpl
> outer_clip
=
7603 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7604 outer_clip
->SetBounds(outer_viewport
);
7605 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7607 scoped_ptr
<LayerImpl
> outer_scroll
=
7608 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7609 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7610 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7611 outer_scroll
->SetBounds(content_size
);
7612 outer_scroll
->SetPosition(gfx::PointF());
7614 scoped_ptr
<LayerImpl
> contents
=
7615 LayerImpl::Create(layer_tree_impl
, 8);
7616 contents
->SetDrawsContent(true);
7617 contents
->SetBounds(content_size
);
7618 contents
->SetPosition(gfx::PointF());
7620 outer_scroll
->AddChild(contents
.Pass());
7621 outer_clip
->AddChild(outer_scroll
.Pass());
7622 inner_scroll
->AddChild(outer_clip
.Pass());
7623 page_scale
->AddChild(inner_scroll
.Pass());
7624 inner_clip
->AddChild(page_scale
.Pass());
7626 inner_clip
->SetHasRenderSurface(true);
7627 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7628 layer_tree_impl
->SetViewportLayersFromIds(
7629 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7630 kOuterViewportScrollLayerId
);
7632 host_impl_
->active_tree()->DidBecomeActive();
7636 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7637 gfx::Size content_size
= gfx::Size(100, 160);
7638 gfx::Size outer_viewport
= gfx::Size(50, 80);
7639 gfx::Size inner_viewport
= gfx::Size(25, 40);
7641 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7643 TestScrollOffsetDelegate scroll_delegate
;
7644 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7646 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7647 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7650 gfx::ScrollOffset inner_expected
;
7651 gfx::ScrollOffset outer_expected
;
7652 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7653 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7655 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7657 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
7658 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7659 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7661 // Outer viewport scrolls first. Then the rest is applied to the inner
7663 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7664 inner_scroll
->CurrentScrollOffset());
7665 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7666 outer_scroll
->CurrentScrollOffset());
7670 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7671 gfx::Size content_size
= gfx::Size(200, 320);
7672 gfx::Size outer_viewport
= gfx::Size(100, 160);
7673 gfx::Size inner_viewport
= gfx::Size(50, 80);
7675 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7677 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7678 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7681 gfx::Vector2dF inner_expected
;
7682 gfx::Vector2dF outer_expected
;
7683 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7684 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7686 // Scrolling the viewport always sets the outer scroll layer as the
7687 // currently scrolling layer.
7688 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7689 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7690 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7691 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7692 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7694 gfx::Vector2d
scroll_delta(inner_viewport
.width() / 2.f
,
7695 inner_viewport
.height() / 2.f
);
7696 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7697 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7698 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), outer_scroll
);
7700 host_impl_
->ScrollEnd();
7701 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7703 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7704 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7706 // Fling past the inner viewport boundry, make sure outer viewport scrolls.
7707 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7708 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7709 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7710 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7711 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7713 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7714 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7715 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7717 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7718 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7719 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7721 host_impl_
->ScrollEnd();
7722 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7724 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7725 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7729 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7730 DiagonalScrollBubblesPerfectlyToInner
) {
7731 gfx::Size content_size
= gfx::Size(200, 320);
7732 gfx::Size outer_viewport
= gfx::Size(100, 160);
7733 gfx::Size inner_viewport
= gfx::Size(50, 80);
7735 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7737 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7738 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7741 gfx::Vector2dF inner_expected
;
7742 gfx::Vector2dF outer_expected
;
7743 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7744 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7746 // Make sure the scroll goes to the inner viewport first.
7747 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7748 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7749 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7750 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7751 InputHandler::GESTURE
));
7753 // Scroll near the edge of the outer viewport.
7754 gfx::Vector2d
scroll_delta(inner_viewport
.width() / 2.f
,
7755 inner_viewport
.height() / 2.f
);
7756 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7757 inner_expected
+= scroll_delta
;
7758 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7759 InputHandler::GESTURE
));
7761 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7762 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7764 // Now diagonal scroll across the outer viewport boundary in a single event.
7765 // The entirety of the scroll should be consumed, as bubbling between inner
7766 // and outer viewport layers is perfect.
7767 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7768 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7769 InputHandler::GESTURE
));
7770 outer_expected
+= scroll_delta
;
7771 inner_expected
+= scroll_delta
;
7772 host_impl_
->ScrollEnd();
7773 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7774 gfx::Point(), InputHandler::GESTURE
));
7776 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7777 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7781 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7782 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7783 gfx::Size content_size
= gfx::Size(100, 160);
7784 gfx::Size outer_viewport
= gfx::Size(50, 80);
7785 gfx::Size inner_viewport
= gfx::Size(25, 40);
7787 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7789 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7790 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7792 scoped_ptr
<LayerImpl
> child
=
7793 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7794 LayerImpl
* child_scroll
= child
.get();
7795 outer_scroll
->children()[0]->AddChild(child
.Pass());
7799 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7801 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7802 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7803 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7804 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7805 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7806 InputHandler::GESTURE
));
7808 // The child should have scrolled up to its limit.
7809 scroll_info
= host_impl_
->ProcessScrollDeltas();
7810 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7812 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7813 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7815 // The first |ScrollBy| after the fling should re-lock the scrolling
7816 // layer to the first layer that scrolled, the inner viewport scroll layer.
7817 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7818 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7819 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7820 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7821 InputHandler::GESTURE
));
7823 // The inner viewport should have scrolled up to its limit.
7824 scroll_info
= host_impl_
->ProcessScrollDeltas();
7825 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7827 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7829 ScrollInfoContains(*scroll_info
, inner_scroll
->id(), scroll_delta
));
7831 // As the locked layer is at its limit, no further scrolling can occur.
7832 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7833 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7834 host_impl_
->ScrollEnd();
7835 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7836 gfx::Point(), InputHandler::GESTURE
));
7840 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7841 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest
) {
7842 gfx::Size content_size
= gfx::Size(100, 160);
7843 gfx::Size outer_viewport
= gfx::Size(50, 80);
7844 gfx::Size inner_viewport
= gfx::Size(25, 40);
7846 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7848 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7849 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7851 scoped_ptr
<LayerImpl
> child
=
7852 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7853 LayerImpl
* child_scroll
= child
.get();
7854 outer_scroll
->children()[0]->AddChild(child
.Pass());
7858 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7859 host_impl_
->RootScrollBegin(InputHandler::GESTURE
));
7860 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7861 host_impl_
->ScrollEnd();
7862 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7863 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7864 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7865 host_impl_
->ScrollEnd();
7868 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7869 NoOverscrollWhenInnerViewportCantScroll
) {
7870 InputHandlerScrollResult scroll_result
;
7871 gfx::Size content_size
= gfx::Size(100, 160);
7872 gfx::Size outer_viewport
= gfx::Size(50, 80);
7873 gfx::Size inner_viewport
= gfx::Size(25, 40);
7874 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7877 // Make inner viewport unscrollable.
7878 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7879 inner_scroll
->set_user_scrollable_horizontal(false);
7880 inner_scroll
->set_user_scrollable_vertical(false);
7882 // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
7883 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7884 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7885 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7886 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
7887 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7889 // When inner viewport is unscrollable, a fling gives zero overscroll.
7890 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
7891 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
7894 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7896 void SetUp() override
{
7897 LayerTreeSettings settings
= DefaultSettings();
7898 settings
.max_memory_for_prepaint_percentage
= 50;
7899 CreateHostImpl(settings
, CreateOutputSurface());
7903 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7904 // Set up a memory policy and percentages which could cause
7905 // 32-bit integer overflows.
7906 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7908 // Verify implicit limits are calculated correctly with no overflows
7909 host_impl_
->SetMemoryPolicy(mem_policy
);
7910 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7911 300u * 1024u * 1024u);
7912 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7913 150u * 1024u * 1024u);
7916 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7917 const gfx::Size
layer_size(100, 100);
7918 gfx::Transform external_transform
;
7919 const gfx::Rect
external_viewport(layer_size
);
7920 const gfx::Rect
external_clip(layer_size
);
7921 const bool resourceless_software_draw
= false;
7922 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7924 host_impl_
->SetExternalDrawConstraints(external_transform
,
7929 resourceless_software_draw
);
7931 EXPECT_TRANSFORMATION_MATRIX_EQ(
7932 external_transform
, layer
->draw_properties().target_space_transform
);
7934 external_transform
.Translate(20, 20);
7935 host_impl_
->SetExternalDrawConstraints(external_transform
,
7940 resourceless_software_draw
);
7942 EXPECT_TRANSFORMATION_MATRIX_EQ(
7943 external_transform
, layer
->draw_properties().target_space_transform
);
7946 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7947 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7950 base::TimeTicks start_time
=
7951 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7953 BeginFrameArgs begin_frame_args
=
7954 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7956 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7957 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7959 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7961 begin_frame_args
.frame_time
= start_time
;
7962 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7963 host_impl_
->Animate();
7964 host_impl_
->UpdateAnimationState(true);
7966 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7967 host_impl_
->DidFinishImplFrame();
7969 begin_frame_args
.frame_time
=
7970 start_time
+ base::TimeDelta::FromMilliseconds(50);
7971 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7972 host_impl_
->Animate();
7973 host_impl_
->UpdateAnimationState(true);
7975 float y
= scrolling_layer
->CurrentScrollOffset().y();
7976 EXPECT_TRUE(y
> 1 && y
< 49);
7979 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7980 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7981 host_impl_
->DidFinishImplFrame();
7983 begin_frame_args
.frame_time
=
7984 start_time
+ base::TimeDelta::FromMilliseconds(200);
7985 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7986 host_impl_
->Animate();
7987 host_impl_
->UpdateAnimationState(true);
7989 y
= scrolling_layer
->CurrentScrollOffset().y();
7990 EXPECT_TRUE(y
> 50 && y
< 100);
7991 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7992 host_impl_
->DidFinishImplFrame();
7994 begin_frame_args
.frame_time
=
7995 start_time
+ base::TimeDelta::FromMilliseconds(250);
7996 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7997 host_impl_
->Animate();
7998 host_impl_
->UpdateAnimationState(true);
8000 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8001 scrolling_layer
->CurrentScrollOffset());
8002 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
8003 host_impl_
->DidFinishImplFrame();
8006 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
8007 TEST_F(LayerTreeHostImplTimelinesTest
, ScrollAnimated
) {
8008 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8011 base::TimeTicks start_time
=
8012 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8014 BeginFrameArgs begin_frame_args
=
8015 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8017 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8018 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8020 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
8022 begin_frame_args
.frame_time
= start_time
;
8023 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8024 host_impl_
->Animate();
8025 host_impl_
->UpdateAnimationState(true);
8027 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
8028 host_impl_
->DidFinishImplFrame();
8030 begin_frame_args
.frame_time
=
8031 start_time
+ base::TimeDelta::FromMilliseconds(50);
8032 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8033 host_impl_
->Animate();
8034 host_impl_
->UpdateAnimationState(true);
8036 float y
= scrolling_layer
->CurrentScrollOffset().y();
8037 EXPECT_TRUE(y
> 1 && y
< 49);
8040 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8041 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8042 host_impl_
->DidFinishImplFrame();
8044 begin_frame_args
.frame_time
=
8045 start_time
+ base::TimeDelta::FromMilliseconds(200);
8046 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8047 host_impl_
->Animate();
8048 host_impl_
->UpdateAnimationState(true);
8050 y
= scrolling_layer
->CurrentScrollOffset().y();
8051 EXPECT_TRUE(y
> 50 && y
< 100);
8052 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
8053 host_impl_
->DidFinishImplFrame();
8055 begin_frame_args
.frame_time
=
8056 start_time
+ base::TimeDelta::FromMilliseconds(250);
8057 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8058 host_impl_
->Animate();
8059 host_impl_
->UpdateAnimationState(true);
8061 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8062 scrolling_layer
->CurrentScrollOffset());
8063 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
8064 host_impl_
->DidFinishImplFrame();
8067 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
8068 host_impl_
->CreatePendingTree();
8070 Region empty_invalidation
;
8071 scoped_refptr
<RasterSource
> pile_with_tiles(
8072 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
8073 gfx::Size(10, 10)));
8075 scoped_ptr
<FakePictureLayerImpl
> layer
=
8076 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
8077 layer
->SetBounds(gfx::Size(10, 10));
8078 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
8079 layer
->SetDrawsContent(true);
8080 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
8081 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
8082 layer
->tilings()->tiling_at(0)->set_resolution(
8083 TileResolution::HIGH_RESOLUTION
);
8084 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
8085 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
8086 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
8087 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
8089 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
8090 host_impl_
->pending_tree()->root_layer());
8092 root_layer
->set_has_valid_tile_priorities(true);
8093 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
8094 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8095 RasterTilePriorityQueue::Type::ALL
);
8096 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
8098 root_layer
->set_has_valid_tile_priorities(false);
8099 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
8100 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8101 RasterTilePriorityQueue::Type::ALL
);
8102 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
8105 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
8106 host_impl_
->CreatePendingTree();
8107 host_impl_
->ActivateSyncTree();
8108 host_impl_
->CreatePendingTree();
8110 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
8112 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
8113 FakePictureLayerImpl::Create(pending_tree
, 10);
8114 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
8115 pending_tree
->SetRootLayer(pending_layer
.Pass());
8116 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
8118 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
8119 pending_tree
->DidBecomeActive();
8120 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8122 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
8123 FakePictureLayerImpl::Create(pending_tree
, 11);
8124 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
8125 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
8126 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
8128 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8129 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
8130 pending_tree
->DidBecomeActive();
8131 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8132 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8134 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
8135 FakePictureLayerImpl::Create(pending_tree
, 12);
8136 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
8137 FakePictureLayerImpl::Create(pending_tree
, 13);
8138 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
8139 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
8140 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
8141 ASSERT_EQ(raw_replica_mask_layer
,
8142 raw_pending_layer
->replica_layer()->mask_layer());
8144 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8145 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8146 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
8147 pending_tree
->DidBecomeActive();
8148 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
8149 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
8150 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
8153 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
8154 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
8155 host_impl_
->SetViewportSize(gfx::Size(50, 50));
8158 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
8160 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
8161 float page_scale_factor
= 1.f
;
8163 // The scroll deltas should have the page scale factor applied.
8165 host_impl_
->active_tree()->PushPageScaleFromMainThread(
8166 page_scale_factor
, min_page_scale
, max_page_scale
);
8167 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
8168 scroll_layer
->SetScrollDelta(gfx::Vector2d());
8170 float page_scale_delta
= 2.f
;
8171 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
8172 host_impl_
->PinchGestureBegin();
8173 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
8174 host_impl_
->PinchGestureEnd();
8175 host_impl_
->ScrollEnd();
8177 gfx::Vector2dF
scroll_delta(0, 5);
8178 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8179 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
8180 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
8182 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
8183 host_impl_
->ScrollEnd();
8184 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8185 scroll_layer
->CurrentScrollOffset());
8189 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
8191 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8192 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
8195 int num_lost_surfaces_
;
8198 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
8199 // Really we just need at least one client notification each time
8200 // we go from having a valid output surface to not having a valid output
8202 EXPECT_EQ(0, num_lost_surfaces_
);
8203 host_impl_
->DidLoseOutputSurface();
8204 EXPECT_EQ(1, num_lost_surfaces_
);
8205 host_impl_
->DidLoseOutputSurface();
8206 EXPECT_LE(1, num_lost_surfaces_
);
8209 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
8210 LayerTreeHostImpl::FrameData frame
;
8211 frame
.render_passes
.push_back(RenderPass::Create());
8212 RenderPass
* pass3
= frame
.render_passes
.back();
8213 frame
.render_passes
.push_back(RenderPass::Create());
8214 RenderPass
* pass2
= frame
.render_passes
.back();
8215 frame
.render_passes
.push_back(RenderPass::Create());
8216 RenderPass
* pass1
= frame
.render_passes
.back();
8218 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8219 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8220 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8222 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8223 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8224 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8226 // Add a quad to each pass so they aren't empty.
8227 SolidColorDrawQuad
* color_quad
;
8228 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8229 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8230 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8231 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8232 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8233 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8235 // pass3 is referenced by pass2.
8236 RenderPassDrawQuad
* rpdq
=
8237 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8238 rpdq
->material
= DrawQuad::RENDER_PASS
;
8239 rpdq
->render_pass_id
= pass3
->id
;
8241 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
8242 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8243 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8244 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8245 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8246 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8247 EXPECT_EQ(1u, frame
.render_passes
.size());
8248 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8251 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
8252 LayerTreeHostImpl::FrameData frame
;
8253 frame
.render_passes
.push_back(RenderPass::Create());
8254 RenderPass
* pass3
= frame
.render_passes
.back();
8255 frame
.render_passes
.push_back(RenderPass::Create());
8256 RenderPass
* pass2
= frame
.render_passes
.back();
8257 frame
.render_passes
.push_back(RenderPass::Create());
8258 RenderPass
* pass1
= frame
.render_passes
.back();
8260 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8261 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8262 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8264 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8265 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8266 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8268 // pass1 is not empty, but pass2 and pass3 are.
8269 SolidColorDrawQuad
* color_quad
;
8270 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8271 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8273 // pass3 is referenced by pass2.
8274 RenderPassDrawQuad
* rpdq
=
8275 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8276 rpdq
->material
= DrawQuad::RENDER_PASS
;
8277 rpdq
->render_pass_id
= pass3
->id
;
8279 // pass2 is referenced by pass1.
8280 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8281 rpdq
->material
= DrawQuad::RENDER_PASS
;
8282 rpdq
->render_pass_id
= pass2
->id
;
8284 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8285 // should be removed.
8286 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8287 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8288 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8289 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8290 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8291 EXPECT_EQ(1u, frame
.render_passes
.size());
8292 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8293 // The RenderPassDrawQuad should be removed from pass1.
8294 EXPECT_EQ(1u, pass1
->quad_list
.size());
8295 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
8298 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
8299 LayerTreeHostImpl::FrameData frame
;
8300 frame
.render_passes
.push_back(RenderPass::Create());
8301 RenderPass
* pass3
= frame
.render_passes
.back();
8302 frame
.render_passes
.push_back(RenderPass::Create());
8303 RenderPass
* pass2
= frame
.render_passes
.back();
8304 frame
.render_passes
.push_back(RenderPass::Create());
8305 RenderPass
* pass1
= frame
.render_passes
.back();
8307 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8308 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8309 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8311 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8312 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8313 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8315 // pass3 is referenced by pass2.
8316 RenderPassDrawQuad
* rpdq
=
8317 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8318 rpdq
->material
= DrawQuad::RENDER_PASS
;
8319 rpdq
->render_pass_id
= pass3
->id
;
8321 // pass2 is referenced by pass1.
8322 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8323 rpdq
->material
= DrawQuad::RENDER_PASS
;
8324 rpdq
->render_pass_id
= pass2
->id
;
8326 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8327 // should be removed. Then pass1 is empty too, but it's the root so it should
8329 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8330 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8331 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8332 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8333 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8334 EXPECT_EQ(1u, frame
.render_passes
.size());
8335 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8336 // The RenderPassDrawQuad should be removed from pass1.
8337 EXPECT_EQ(0u, pass1
->quad_list
.size());
8340 class FakeVideoFrameController
: public VideoFrameController
{
8342 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
8343 begin_frame_args_
= args
;
8344 did_draw_frame_
= false;
8347 void DidDrawFrame() override
{ did_draw_frame_
= true; }
8349 const BeginFrameArgs
& begin_frame_args() const { return begin_frame_args_
; }
8351 bool did_draw_frame() const { return did_draw_frame_
; }
8354 BeginFrameArgs begin_frame_args_
;
8355 bool did_draw_frame_
= false;
8358 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
8359 BeginFrameArgs begin_frame_args
=
8360 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8361 FakeVideoFrameController controller
;
8363 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8364 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8365 host_impl_
->AddVideoFrameController(&controller
);
8366 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8367 host_impl_
->DidFinishImplFrame();
8369 EXPECT_FALSE(controller
.did_draw_frame());
8370 LayerTreeHostImpl::FrameData frame
;
8371 host_impl_
->DidDrawAllLayers(frame
);
8372 EXPECT_TRUE(controller
.did_draw_frame());
8374 controller
.OnBeginFrame(begin_frame_args
);
8375 EXPECT_FALSE(controller
.did_draw_frame());
8376 host_impl_
->RemoveVideoFrameController(&controller
);
8377 host_impl_
->DidDrawAllLayers(frame
);
8378 EXPECT_FALSE(controller
.did_draw_frame());
8381 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
8382 BeginFrameArgs begin_frame_args
=
8383 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8384 FakeVideoFrameController controller
;
8386 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8387 host_impl_
->DidFinishImplFrame();
8389 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8390 host_impl_
->AddVideoFrameController(&controller
);
8391 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8393 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8394 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8395 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8396 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8398 EXPECT_FALSE(controller
.did_draw_frame());
8399 LayerTreeHostImpl::FrameData frame
;
8400 host_impl_
->DidDrawAllLayers(frame
);
8401 EXPECT_TRUE(controller
.did_draw_frame());
8403 controller
.OnBeginFrame(begin_frame_args
);
8404 EXPECT_FALSE(controller
.did_draw_frame());
8405 host_impl_
->RemoveVideoFrameController(&controller
);
8406 host_impl_
->DidDrawAllLayers(frame
);
8407 EXPECT_FALSE(controller
.did_draw_frame());
8410 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
8411 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8413 host_impl_
->SetHasGpuRasterizationTrigger(true);
8414 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8415 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
8416 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8418 host_impl_
->SetHasGpuRasterizationTrigger(false);
8419 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8420 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
8421 host_impl_
->gpu_rasterization_status());
8422 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8424 host_impl_
->SetHasGpuRasterizationTrigger(true);
8425 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8426 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
8427 host_impl_
->gpu_rasterization_status());
8428 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8429 EXPECT_FALSE(host_impl_
->use_msaa());
8431 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
8432 TestWebGraphicsContext3D::Create();
8433 context_with_msaa
->SetMaxSamples(8);
8435 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
8436 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
8437 EXPECT_TRUE(CreateHostImpl(
8438 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
8439 host_impl_
->SetHasGpuRasterizationTrigger(true);
8440 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8441 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
8442 host_impl_
->gpu_rasterization_status());
8443 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8444 EXPECT_TRUE(host_impl_
->use_msaa());
8446 LayerTreeSettings settings
= DefaultSettings();
8447 settings
.gpu_rasterization_enabled
= false;
8448 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8449 host_impl_
->SetHasGpuRasterizationTrigger(true);
8450 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8451 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
8452 host_impl_
->gpu_rasterization_status());
8453 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8455 settings
.gpu_rasterization_forced
= true;
8456 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8458 host_impl_
->SetHasGpuRasterizationTrigger(false);
8459 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8460 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
8461 host_impl_
->gpu_rasterization_status());
8462 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8465 // A mock output surface which lets us detect calls to ForceReclaimResources.
8466 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
8468 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
8469 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8470 TestContextProvider::Create(), TestContextProvider::CreateWorker(),
8474 MOCK_METHOD0(ForceReclaimResources
, void());
8477 MockReclaimResourcesOutputSurface(
8478 scoped_refptr
<ContextProvider
> context_provider
,
8479 scoped_refptr
<ContextProvider
> worker_context_provider
,
8480 bool delegated_rendering
)
8481 : FakeOutputSurface(context_provider
,
8482 worker_context_provider
,
8483 delegated_rendering
) {}
8486 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8487 // being reclaimed to block drawing between BeginCommit / Swap. This test
8488 // ensures that BeginCommit triggers ForceReclaimResources. See
8489 // crbug.com/489515.
8490 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
8491 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
8492 MockReclaimResourcesOutputSurface::Create3d());
8493 // Hold an unowned pointer to the output surface to use for mock expectations.
8494 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
8496 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
8497 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
8498 host_impl_
->BeginCommit();