1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "base/location.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "cc/animation/scrollbar_animation_controller_thinning.h"
17 #include "cc/animation/transform_operations.h"
18 #include "cc/base/math_util.h"
19 #include "cc/input/page_scale_animation.h"
20 #include "cc/input/top_controls_manager.h"
21 #include "cc/layers/append_quads_data.h"
22 #include "cc/layers/delegated_renderer_layer_impl.h"
23 #include "cc/layers/heads_up_display_layer_impl.h"
24 #include "cc/layers/io_surface_layer_impl.h"
25 #include "cc/layers/layer_impl.h"
26 #include "cc/layers/painted_scrollbar_layer_impl.h"
27 #include "cc/layers/render_surface_impl.h"
28 #include "cc/layers/solid_color_layer_impl.h"
29 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
30 #include "cc/layers/texture_layer_impl.h"
31 #include "cc/layers/video_layer_impl.h"
32 #include "cc/layers/viewport.h"
33 #include "cc/output/begin_frame_args.h"
34 #include "cc/output/compositor_frame_ack.h"
35 #include "cc/output/compositor_frame_metadata.h"
36 #include "cc/output/copy_output_request.h"
37 #include "cc/output/copy_output_result.h"
38 #include "cc/output/gl_renderer.h"
39 #include "cc/output/latency_info_swap_promise.h"
40 #include "cc/quads/render_pass_draw_quad.h"
41 #include "cc/quads/solid_color_draw_quad.h"
42 #include "cc/quads/texture_draw_quad.h"
43 #include "cc/quads/tile_draw_quad.h"
44 #include "cc/test/animation_test_common.h"
45 #include "cc/test/begin_frame_args_test.h"
46 #include "cc/test/fake_layer_tree_host_impl.h"
47 #include "cc/test/fake_output_surface.h"
48 #include "cc/test/fake_output_surface_client.h"
49 #include "cc/test/fake_picture_layer_impl.h"
50 #include "cc/test/fake_picture_pile_impl.h"
51 #include "cc/test/fake_proxy.h"
52 #include "cc/test/fake_video_frame_provider.h"
53 #include "cc/test/geometry_test_utils.h"
54 #include "cc/test/gpu_rasterization_enabled_settings.h"
55 #include "cc/test/layer_test_common.h"
56 #include "cc/test/layer_tree_test.h"
57 #include "cc/test/test_gpu_memory_buffer_manager.h"
58 #include "cc/test/test_shared_bitmap_manager.h"
59 #include "cc/test/test_task_graph_runner.h"
60 #include "cc/test/test_web_graphics_context_3d.h"
61 #include "cc/trees/layer_tree_impl.h"
62 #include "cc/trees/single_thread_proxy.h"
63 #include "media/base/media.h"
64 #include "testing/gmock/include/gmock/gmock.h"
65 #include "testing/gtest/include/gtest/gtest.h"
66 #include "third_party/skia/include/core/SkMallocPixelRef.h"
67 #include "ui/gfx/geometry/rect_conversions.h"
68 #include "ui/gfx/geometry/size_conversions.h"
69 #include "ui/gfx/geometry/vector2d_conversions.h"
71 using ::testing::Mock
;
72 using ::testing::Return
;
73 using ::testing::AnyNumber
;
74 using ::testing::AtLeast
;
76 using media::VideoFrame
;
81 class LayerTreeHostImplTest
: public testing::Test
,
82 public LayerTreeHostImplClient
{
84 LayerTreeHostImplTest()
85 : proxy_(base::ThreadTaskRunnerHandle::Get(),
86 base::ThreadTaskRunnerHandle::Get()),
87 always_impl_thread_(&proxy_
),
88 always_main_thread_blocked_(&proxy_
),
89 on_can_draw_state_changed_called_(false),
90 did_notify_ready_to_activate_(false),
91 did_request_commit_(false),
92 did_request_redraw_(false),
93 did_request_animate_(false),
94 did_request_prepare_tiles_(false),
95 did_complete_page_scale_animation_(false),
96 reduce_memory_result_(true) {
97 media::InitializeMediaLibrary();
100 LayerTreeSettings
DefaultSettings() {
101 LayerTreeSettings settings
;
102 settings
.minimum_occlusion_tracking_size
= gfx::Size();
103 settings
.renderer_settings
.texture_id_allocation_chunk_size
= 1;
104 settings
.gpu_rasterization_enabled
= true;
108 void SetUp() override
{
109 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
112 void TearDown() override
{}
114 void UpdateRendererCapabilitiesOnImplThread() override
{}
115 void DidLoseOutputSurfaceOnImplThread() override
{}
116 void CommitVSyncParameters(base::TimeTicks timebase
,
117 base::TimeDelta interval
) override
{}
118 void SetEstimatedParentDrawTime(base::TimeDelta draw_time
) override
{}
119 void SetMaxSwapsPendingOnImplThread(int max
) override
{}
120 void DidSwapBuffersOnImplThread() override
{}
121 void DidSwapBuffersCompleteOnImplThread() override
{}
122 void OnCanDrawStateChanged(bool can_draw
) override
{
123 on_can_draw_state_changed_called_
= true;
125 void NotifyReadyToActivate() override
{
126 did_notify_ready_to_activate_
= true;
127 host_impl_
->ActivateSyncTree();
129 void NotifyReadyToDraw() override
{}
130 void SetNeedsRedrawOnImplThread() override
{ did_request_redraw_
= true; }
131 void SetNeedsRedrawRectOnImplThread(const gfx::Rect
& damage_rect
) override
{
132 did_request_redraw_
= true;
134 void SetNeedsAnimateOnImplThread() override
{ did_request_animate_
= true; }
135 void SetNeedsPrepareTilesOnImplThread() override
{
136 did_request_prepare_tiles_
= true;
138 void SetNeedsCommitOnImplThread() override
{ did_request_commit_
= true; }
139 void SetVideoNeedsBeginFrames(bool needs_begin_frames
) override
{}
140 void PostAnimationEventsToMainThreadOnImplThread(
141 scoped_ptr
<AnimationEventsVector
> events
) override
{}
142 bool IsInsideDraw() override
{ return false; }
143 void RenewTreePriority() override
{}
144 void PostDelayedAnimationTaskOnImplThread(const base::Closure
& task
,
145 base::TimeDelta delay
) override
{
146 animation_task_
= task
;
147 requested_animation_delay_
= delay
;
149 void DidActivateSyncTree() override
{}
150 void WillPrepareTiles() override
{}
151 void DidPrepareTiles() override
{}
152 void DidCompletePageScaleAnimationOnImplThread() override
{
153 did_complete_page_scale_animation_
= true;
155 void OnDrawForOutputSurface() override
{}
156 void PostFrameTimingEventsOnImplThread(
157 scoped_ptr
<FrameTimingTracker::CompositeTimingSet
> composite_events
,
158 scoped_ptr
<FrameTimingTracker::MainFrameTimingSet
> main_frame_events
)
161 void set_reduce_memory_result(bool reduce_memory_result
) {
162 reduce_memory_result_
= reduce_memory_result
;
165 virtual bool CreateHostImpl(const LayerTreeSettings
& settings
,
166 scoped_ptr
<OutputSurface
> output_surface
) {
167 host_impl_
= LayerTreeHostImpl::Create(
168 settings
, this, &proxy_
, &stats_instrumentation_
,
169 &shared_bitmap_manager_
, &gpu_memory_buffer_manager_
,
170 &task_graph_runner_
, 0);
171 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
172 host_impl_
->SetViewportSize(gfx::Size(10, 10));
173 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
174 // Set the BeginFrameArgs so that methods which use it are able to.
175 host_impl_
->WillBeginImplFrame(CreateBeginFrameArgsForTesting(
176 BEGINFRAME_FROM_HERE
,
177 base::TimeTicks() + base::TimeDelta::FromMilliseconds(1)));
178 host_impl_
->DidFinishImplFrame();
182 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
183 root
->SetPosition(gfx::PointF());
184 root
->SetBounds(gfx::Size(10, 10));
185 root
->SetDrawsContent(true);
186 root
->draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
187 root
->SetHasRenderSurface(true);
188 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
191 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
192 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
193 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
194 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
197 static ::testing::AssertionResult
ScrollInfoContains(
198 const ScrollAndScaleSet
& scroll_info
,
200 const gfx::Vector2d
& scroll_delta
) {
201 int times_encountered
= 0;
203 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
204 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
207 if (scroll_delta
!= scroll_info
.scrolls
[i
].scroll_delta
) {
208 return ::testing::AssertionFailure()
209 << "Expected " << scroll_delta
.ToString() << ", not "
210 << scroll_info
.scrolls
[i
].scroll_delta
.ToString();
215 if (times_encountered
!= 1)
216 return ::testing::AssertionFailure() << "No layer found with id " << id
;
217 return ::testing::AssertionSuccess();
220 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
221 int times_encountered
= 0;
223 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
224 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
229 ASSERT_EQ(0, times_encountered
);
232 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
233 const gfx::Size
& content_size
) {
234 // Create both an inner viewport scroll layer and an outer viewport scroll
235 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
236 // 0x0, so the scrolls will be applied directly to the inner viewport.
237 const int kOuterViewportClipLayerId
= 116;
238 const int kOuterViewportScrollLayerId
= 117;
239 const int kContentLayerId
= 118;
240 const int kInnerViewportScrollLayerId
= 2;
241 const int kInnerViewportClipLayerId
= 4;
242 const int kPageScaleLayerId
= 5;
244 scoped_ptr
<LayerImpl
> root
=
245 LayerImpl::Create(layer_tree_impl
, 1);
246 root
->SetBounds(content_size
);
247 root
->SetPosition(gfx::PointF());
248 root
->SetHasRenderSurface(true);
250 scoped_ptr
<LayerImpl
> inner_scroll
=
251 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
252 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
253 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
255 scoped_ptr
<LayerImpl
> inner_clip
=
256 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
257 inner_clip
->SetBounds(
258 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
260 scoped_ptr
<LayerImpl
> page_scale
=
261 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
263 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
264 inner_scroll
->SetBounds(content_size
);
265 inner_scroll
->SetPosition(gfx::PointF());
267 scoped_ptr
<LayerImpl
> outer_clip
=
268 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
269 outer_clip
->SetBounds(content_size
);
270 outer_clip
->SetIsContainerForFixedPositionLayers(true);
272 scoped_ptr
<LayerImpl
> outer_scroll
=
273 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
274 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
275 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
276 outer_scroll
->SetBounds(content_size
);
277 outer_scroll
->SetPosition(gfx::PointF());
279 scoped_ptr
<LayerImpl
> contents
=
280 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
281 contents
->SetDrawsContent(true);
282 contents
->SetBounds(content_size
);
283 contents
->SetPosition(gfx::PointF());
285 outer_scroll
->AddChild(contents
.Pass());
286 outer_clip
->AddChild(outer_scroll
.Pass());
287 inner_scroll
->AddChild(outer_clip
.Pass());
288 page_scale
->AddChild(inner_scroll
.Pass());
289 inner_clip
->AddChild(page_scale
.Pass());
290 root
->AddChild(inner_clip
.Pass());
292 layer_tree_impl
->SetRootLayer(root
.Pass());
293 layer_tree_impl
->SetViewportLayersFromIds(
294 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
295 kOuterViewportScrollLayerId
);
297 layer_tree_impl
->DidBecomeActive();
298 return layer_tree_impl
->InnerViewportScrollLayer();
301 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
302 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
303 host_impl_
->active_tree(), content_size
);
304 host_impl_
->active_tree()->DidBecomeActive();
308 // Sets up a typical virtual viewport setup with one child content layer.
309 // Returns a pointer to the content layer.
310 LayerImpl
* CreateBasicVirtualViewportLayers(const gfx::Size
& viewport_size
,
311 const gfx::Size
& content_size
) {
312 // CreateScrollAndContentsLayers makes the outer viewport unscrollable and
313 // the inner a different size from the outer. We'll reuse its layer
314 // hierarchy but adjust the sizing to our needs.
315 CreateScrollAndContentsLayers(host_impl_
->active_tree(), content_size
);
317 LayerImpl
* content_layer
=
318 host_impl_
->OuterViewportScrollLayer()->children().back();
319 content_layer
->SetBounds(content_size
);
320 host_impl_
->OuterViewportScrollLayer()->SetBounds(content_size
);
322 LayerImpl
* outer_clip
= host_impl_
->OuterViewportScrollLayer()->parent();
323 outer_clip
->SetBounds(viewport_size
);
325 LayerImpl
* inner_clip_layer
=
326 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
327 inner_clip_layer
->SetBounds(viewport_size
);
328 host_impl_
->InnerViewportScrollLayer()->SetBounds(viewport_size
);
330 host_impl_
->SetViewportSize(viewport_size
);
331 host_impl_
->active_tree()->DidBecomeActive();
333 return content_layer
;
336 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
337 const gfx::Size
& size
,
338 LayerImpl
* clip_layer
) {
340 DCHECK(id
!= clip_layer
->id());
341 scoped_ptr
<LayerImpl
> layer
=
342 LayerImpl::Create(host_impl_
->active_tree(), id
);
343 layer
->SetScrollClipLayer(clip_layer
->id());
344 layer
->SetDrawsContent(true);
345 layer
->SetBounds(size
);
346 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
351 LayerTreeHostImpl::FrameData frame
;
352 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
353 host_impl_
->DrawLayers(&frame
);
354 host_impl_
->DidDrawAllLayers(frame
);
357 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
358 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
359 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
360 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
361 float device_scale_factor
);
363 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
364 // Note: It is not possible to disable the renderer once it has been set,
365 // so we do not need to test that disabling the renderer notifies us
366 // that can_draw changed.
367 EXPECT_FALSE(host_impl_
->CanDraw());
368 on_can_draw_state_changed_called_
= false;
370 // Set up the root layer, which allows us to draw.
371 SetupScrollAndContentsLayers(gfx::Size(100, 100));
372 EXPECT_TRUE(host_impl_
->CanDraw());
373 EXPECT_TRUE(on_can_draw_state_changed_called_
);
374 on_can_draw_state_changed_called_
= false;
376 // Toggle the root layer to make sure it toggles can_draw
377 host_impl_
->active_tree()->SetRootLayer(nullptr);
378 EXPECT_FALSE(host_impl_
->CanDraw());
379 EXPECT_TRUE(on_can_draw_state_changed_called_
);
380 on_can_draw_state_changed_called_
= false;
382 SetupScrollAndContentsLayers(gfx::Size(100, 100));
383 EXPECT_TRUE(host_impl_
->CanDraw());
384 EXPECT_TRUE(on_can_draw_state_changed_called_
);
385 on_can_draw_state_changed_called_
= false;
387 // Toggle the device viewport size to make sure it toggles can_draw.
388 host_impl_
->SetViewportSize(gfx::Size());
390 EXPECT_TRUE(host_impl_
->CanDraw());
392 EXPECT_FALSE(host_impl_
->CanDraw());
394 EXPECT_TRUE(on_can_draw_state_changed_called_
);
395 on_can_draw_state_changed_called_
= false;
397 host_impl_
->SetViewportSize(gfx::Size(100, 100));
398 EXPECT_TRUE(host_impl_
->CanDraw());
399 EXPECT_TRUE(on_can_draw_state_changed_called_
);
400 on_can_draw_state_changed_called_
= false;
403 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
406 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
407 return FakeOutputSurface::Create3d();
410 void DrawOneFrame() {
411 LayerTreeHostImpl::FrameData frame_data
;
412 host_impl_
->PrepareToDraw(&frame_data
);
413 host_impl_
->DidDrawAllLayers(frame_data
);
417 DebugScopedSetImplThread always_impl_thread_
;
418 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
420 TestSharedBitmapManager shared_bitmap_manager_
;
421 TestGpuMemoryBufferManager gpu_memory_buffer_manager_
;
422 TestTaskGraphRunner task_graph_runner_
;
423 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
424 FakeRenderingStatsInstrumentation stats_instrumentation_
;
425 bool on_can_draw_state_changed_called_
;
426 bool did_notify_ready_to_activate_
;
427 bool did_request_commit_
;
428 bool did_request_redraw_
;
429 bool did_request_animate_
;
430 bool did_request_prepare_tiles_
;
431 bool did_complete_page_scale_animation_
;
432 bool reduce_memory_result_
;
433 base::Closure animation_task_
;
434 base::TimeDelta requested_animation_delay_
;
437 // A test fixture for new animation timelines tests.
438 class LayerTreeHostImplTimelinesTest
: public LayerTreeHostImplTest
{
440 void SetUp() override
{
441 LayerTreeSettings settings
= DefaultSettings();
442 settings
.use_compositor_animation_timelines
= true;
443 CreateHostImpl(settings
, CreateOutputSurface());
447 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
448 bool always_draw
= false;
449 CheckNotifyCalledIfCanDrawChanged(always_draw
);
452 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
453 CreateHostImpl(DefaultSettings(),
454 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
456 bool always_draw
= true;
457 CheckNotifyCalledIfCanDrawChanged(always_draw
);
460 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
461 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
463 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
464 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
467 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
469 scoped_ptr
<LayerImpl
> root
=
470 LayerImpl::Create(host_impl_
->active_tree(), 1);
471 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
472 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
473 root
->children()[1]->AddChild(
474 LayerImpl::Create(host_impl_
->active_tree(), 4));
475 root
->children()[1]->AddChild(
476 LayerImpl::Create(host_impl_
->active_tree(), 5));
477 root
->children()[1]->children()[0]->AddChild(
478 LayerImpl::Create(host_impl_
->active_tree(), 6));
479 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
481 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
483 ExpectClearedScrollDeltasRecursive(root
);
485 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
487 scroll_info
= host_impl_
->ProcessScrollDeltas();
488 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
489 ExpectClearedScrollDeltasRecursive(root
);
491 scroll_info
= host_impl_
->ProcessScrollDeltas();
492 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
493 ExpectClearedScrollDeltasRecursive(root
);
496 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
497 gfx::ScrollOffset
scroll_offset(20, 30);
498 gfx::Vector2d
scroll_delta(11, -15);
500 scoped_ptr
<LayerImpl
> root_clip
=
501 LayerImpl::Create(host_impl_
->active_tree(), 2);
502 scoped_ptr
<LayerImpl
> root
=
503 LayerImpl::Create(host_impl_
->active_tree(), 1);
504 root_clip
->SetBounds(gfx::Size(10, 10));
505 LayerImpl
* root_layer
= root
.get();
506 root_clip
->AddChild(root
.Pass());
507 root_layer
->SetBounds(gfx::Size(110, 110));
508 root_layer
->SetScrollClipLayer(root_clip
->id());
509 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
510 root_layer
->ScrollBy(scroll_delta
);
511 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
513 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
515 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
517 scroll_info
= host_impl_
->ProcessScrollDeltas();
518 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
519 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(), scroll_delta
));
521 gfx::Vector2d
scroll_delta2(-5, 27);
522 root
->ScrollBy(scroll_delta2
);
523 scroll_info
= host_impl_
->ProcessScrollDeltas();
524 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
525 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
526 scroll_delta
+ scroll_delta2
));
528 root
->ScrollBy(gfx::Vector2d());
529 scroll_info
= host_impl_
->ProcessScrollDeltas();
530 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, root
->id(),
531 scroll_delta
+ scroll_delta2
));
534 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
535 SetupScrollAndContentsLayers(gfx::Size(100, 100));
536 host_impl_
->SetViewportSize(gfx::Size(50, 50));
539 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
540 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
541 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
542 InputHandler::WHEEL
));
543 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
544 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
545 InputHandler::WHEEL
));
546 host_impl_
->ScrollEnd();
547 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
548 InputHandler::WHEEL
));
549 EXPECT_TRUE(did_request_redraw_
);
550 EXPECT_TRUE(did_request_commit_
);
553 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
554 SetupScrollAndContentsLayers(gfx::Size(100, 100));
555 host_impl_
->SetViewportSize(gfx::Size(50, 50));
558 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
559 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
560 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
561 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
562 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
563 host_impl_
->ScrollEnd();
564 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
567 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
568 // We should not crash when trying to scroll an empty layer tree.
569 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
570 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
573 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
574 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
575 TestWebGraphicsContext3D::Create();
576 context_owned
->set_context_lost(true);
578 // Initialization will fail.
579 EXPECT_FALSE(CreateHostImpl(
580 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
582 SetupScrollAndContentsLayers(gfx::Size(100, 100));
584 // We should not crash when trying to scroll after the renderer initialization
586 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
587 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
590 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
591 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
592 host_impl_
->SetViewportSize(gfx::Size(50, 50));
595 // We should not crash if the tree is replaced while we are scrolling.
596 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
597 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
598 host_impl_
->active_tree()->DetachLayerTree();
600 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
602 // We should still be scrolling, because the scrolled layer also exists in the
604 gfx::Vector2d
scroll_delta(0, 10);
605 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
606 host_impl_
->ScrollEnd();
607 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
609 ScrollInfoContains(*scroll_info
, scroll_layer
->id(), scroll_delta
));
612 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
613 SetupScrollAndContentsLayers(gfx::Size(100, 100));
614 host_impl_
->SetViewportSize(gfx::Size(50, 50));
616 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
618 // With registered event handlers, wheel scrolls don't necessarily
619 // have to go to the main thread.
620 root
->SetHaveWheelEventHandlers(true);
621 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
622 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
623 host_impl_
->ScrollEnd();
625 // But typically the scroll-blocks-on mode will require them to.
626 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
627 SCROLL_BLOCKS_ON_START_TOUCH
);
628 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
629 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
631 // But gesture scrolls can still be handled.
632 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
633 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
634 host_impl_
->ScrollEnd();
636 // And if the handlers go away, wheel scrolls can again be processed
637 // on impl (despite the scroll-blocks-on mode).
638 root
->SetHaveWheelEventHandlers(false);
639 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
640 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
641 host_impl_
->ScrollEnd();
644 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
645 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
646 host_impl_
->SetViewportSize(gfx::Size(50, 50));
648 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
650 LayerImpl
* child
= 0;
652 scoped_ptr
<LayerImpl
> child_layer
=
653 LayerImpl::Create(host_impl_
->active_tree(), 6);
654 child
= child_layer
.get();
655 child_layer
->SetDrawsContent(true);
656 child_layer
->SetPosition(gfx::PointF(0, 20));
657 child_layer
->SetBounds(gfx::Size(50, 50));
658 scroll
->AddChild(child_layer
.Pass());
661 // Touch handler regions determine whether touch events block scroll.
662 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
663 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
664 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
665 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
666 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
668 // But they don't influence the actual handling of the scroll gestures.
669 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
670 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
671 host_impl_
->ScrollEnd();
673 // It's the union of scroll-blocks-on mode bits across all layers in the
674 // scroll paret chain that matters.
675 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
676 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
677 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
678 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
679 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
682 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
683 SetupScrollAndContentsLayers(gfx::Size(100, 100));
684 host_impl_
->SetViewportSize(gfx::Size(50, 50));
686 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
688 // With registered scroll handlers, scrolls don't generally have to go
689 // to the main thread.
690 root
->SetHaveScrollEventHandlers(true);
691 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
692 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
693 host_impl_
->ScrollEnd();
695 // Even the default scroll blocks on mode doesn't require this.
696 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
697 SCROLL_BLOCKS_ON_START_TOUCH
);
698 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
699 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
700 host_impl_
->ScrollEnd();
702 // But the page can opt in to blocking on scroll event handlers.
703 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
704 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
705 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
707 // GESTURE and WHEEL scrolls behave identically in this regard.
708 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
709 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
711 // And if the handlers go away, scrolls can again be processed on impl
712 // (despite the scroll-blocks-on mode).
713 root
->SetHaveScrollEventHandlers(false);
714 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
715 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
716 host_impl_
->ScrollEnd();
719 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
720 host_impl_
->SetViewportSize(gfx::Size(50, 50));
722 // Create a normal scrollable root layer
723 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
724 LayerImpl
* root_child
= root_scroll
->children()[0];
725 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
728 // Create two child scrollable layers
729 LayerImpl
* child1
= 0;
731 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
732 LayerImpl::Create(host_impl_
->active_tree(), 6);
733 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
734 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
735 child1
= scrollable_child_1
.get();
736 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
737 scrollable_child_1
->SetHaveWheelEventHandlers(true);
738 scrollable_child_1
->SetHaveScrollEventHandlers(true);
739 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
740 root_child
->AddChild(scrollable_child_clip_1
.Pass());
743 LayerImpl
* child2
= 0;
745 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
746 LayerImpl::Create(host_impl_
->active_tree(), 8);
747 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
748 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
749 child2
= scrollable_child_2
.get();
750 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
751 scrollable_child_2
->SetHaveWheelEventHandlers(true);
752 scrollable_child_2
->SetHaveScrollEventHandlers(true);
753 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
754 root_child
->AddChild(scrollable_child_clip_2
.Pass());
757 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
758 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
759 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
760 host_impl_
->ScrollEnd();
761 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
762 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
763 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
765 // But not those that hit only other layers.
766 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
767 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
768 host_impl_
->ScrollEnd();
770 // It's the union of bits set across the scroll ancestor chain that matters.
771 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
772 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
773 host_impl_
->ScrollEnd();
774 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
775 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
776 host_impl_
->ScrollEnd();
777 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
778 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
779 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
780 host_impl_
->ScrollEnd();
781 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
782 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
783 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
784 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
785 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
786 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
787 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
790 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
791 SetupScrollAndContentsLayers(gfx::Size(100, 100));
792 host_impl_
->SetViewportSize(gfx::Size(50, 50));
795 // Ignore the fling since no layer is being scrolled
796 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
798 // Start scrolling a layer
799 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
800 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
802 // Now the fling should go ahead since we've started scrolling a layer
803 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
806 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
807 SetupScrollAndContentsLayers(gfx::Size(100, 100));
808 host_impl_
->SetViewportSize(gfx::Size(50, 50));
811 // Ignore the fling since no layer is being scrolled
812 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
814 // Start scrolling a layer
815 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
816 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
818 // Now the fling should go ahead since we've started scrolling a layer
819 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
822 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
823 SetupScrollAndContentsLayers(gfx::Size(100, 100));
824 host_impl_
->SetViewportSize(gfx::Size(50, 50));
826 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
828 root
->SetShouldScrollOnMainThread(true);
830 // Start scrolling a layer
831 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
832 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
834 // The fling should be ignored since there's no layer being scrolled impl-side
835 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
838 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
839 SetupScrollAndContentsLayers(gfx::Size(100, 100));
840 host_impl_
->SetViewportSize(gfx::Size(50, 50));
842 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
844 root
->SetShouldScrollOnMainThread(true);
846 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
847 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
848 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
849 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
852 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
853 SetupScrollAndContentsLayers(gfx::Size(200, 200));
854 host_impl_
->SetViewportSize(gfx::Size(100, 100));
856 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
857 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
861 // All scroll types inside the non-fast scrollable region should fail.
862 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
863 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
864 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
865 InputHandler::WHEEL
));
866 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
867 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
868 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
869 InputHandler::GESTURE
));
871 // All scroll types outside this region should succeed.
872 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
873 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
874 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
875 InputHandler::GESTURE
));
876 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
877 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
878 InputHandler::GESTURE
));
879 host_impl_
->ScrollEnd();
880 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
881 InputHandler::GESTURE
));
882 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
883 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
884 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
885 InputHandler::GESTURE
));
886 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
887 host_impl_
->ScrollEnd();
888 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
889 InputHandler::GESTURE
));
892 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
893 SetupScrollAndContentsLayers(gfx::Size(200, 200));
894 host_impl_
->SetViewportSize(gfx::Size(100, 100));
896 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
897 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
898 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
902 // This point would fall into the non-fast scrollable region except that we've
903 // moved the layer down by 25 pixels.
904 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
905 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
906 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
907 InputHandler::WHEEL
));
908 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
909 host_impl_
->ScrollEnd();
911 // This point is still inside the non-fast region.
912 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
913 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
916 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
917 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
918 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
919 host_impl_
->SetViewportSize(gfx::Size(50, 50));
922 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
923 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
924 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
925 host_impl_
->ScrollEnd();
926 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
929 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
930 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
931 scroll_layer
->SetHaveScrollEventHandlers(true);
932 host_impl_
->SetViewportSize(gfx::Size(50, 50));
935 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
936 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
937 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
938 host_impl_
->ScrollEnd();
939 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
942 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
943 SetupScrollAndContentsLayers(gfx::Size(200, 200));
944 host_impl_
->SetViewportSize(gfx::Size(100, 100));
948 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
949 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
951 // Trying to scroll to the left/top will not succeed.
953 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
955 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
957 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
959 // Scrolling to the right/bottom will succeed.
961 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
963 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
965 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
967 // Scrolling to left/top will now succeed.
969 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
971 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
973 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
975 // Scrolling diagonally against an edge will succeed.
977 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
979 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
981 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
983 // Trying to scroll more than the available space will also succeed.
985 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
988 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
989 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
990 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
994 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
995 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
997 // Trying to scroll without a vertical scrollbar will fail.
998 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
999 gfx::Point(), SCROLL_FORWARD
));
1000 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
1001 gfx::Point(), SCROLL_BACKWARD
));
1003 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
1004 PaintedScrollbarLayerImpl::Create(
1005 host_impl_
->active_tree(),
1008 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1009 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1010 vertical_scrollbar
.get());
1012 // Trying to scroll with a vertical scrollbar will succeed.
1013 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1014 gfx::Point(), SCROLL_FORWARD
));
1015 EXPECT_FLOAT_EQ(875.f
,
1016 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1017 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1018 gfx::Point(), SCROLL_BACKWARD
));
1021 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1022 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1023 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1025 gfx::Size
overflow_size(400, 400);
1026 ASSERT_EQ(1u, scroll_layer
->children().size());
1027 LayerImpl
* overflow
= scroll_layer
->children()[0];
1028 overflow
->SetBounds(overflow_size
);
1029 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1030 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1031 overflow
->SetPosition(gfx::PointF());
1034 gfx::Point
scroll_position(10, 10);
1036 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1037 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1038 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1039 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1041 gfx::Vector2dF
scroll_delta(10, 10);
1042 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1043 host_impl_
->ScrollEnd();
1044 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1045 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1047 overflow
->set_user_scrollable_horizontal(false);
1049 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1050 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1051 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1052 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1054 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1055 host_impl_
->ScrollEnd();
1056 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1057 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1059 overflow
->set_user_scrollable_vertical(false);
1061 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1062 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1063 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1064 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1066 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1067 host_impl_
->ScrollEnd();
1068 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1069 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1072 TEST_F(LayerTreeHostImplTest
, AnimationSchedulingPendingTree
) {
1073 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1075 host_impl_
->CreatePendingTree();
1076 host_impl_
->pending_tree()->SetRootLayer(
1077 LayerImpl::Create(host_impl_
->pending_tree(), 1));
1078 LayerImpl
* root
= host_impl_
->pending_tree()->root_layer();
1079 root
->SetBounds(gfx::Size(50, 50));
1080 root
->SetHasRenderSurface(true);
1082 root
->AddChild(LayerImpl::Create(host_impl_
->pending_tree(), 2));
1083 LayerImpl
* child
= root
->children()[0];
1084 child
->SetBounds(gfx::Size(10, 10));
1085 child
->draw_properties().visible_layer_rect
= gfx::Rect(10, 10);
1086 child
->SetDrawsContent(true);
1087 AddAnimatedTransformToLayer(child
, 10.0, 3, 0);
1089 EXPECT_FALSE(did_request_animate_
);
1090 EXPECT_FALSE(did_request_redraw_
);
1091 EXPECT_FALSE(did_request_commit_
);
1093 host_impl_
->Animate();
1095 // An animation exists on the pending layer. Doing Animate() requests another
1097 // In reality, animations without has_set_start_time() == true do not need to
1098 // be continuously ticked on the pending tree, so it should not request
1099 // another animation frame here. But we currently do so blindly if any
1100 // animation exists.
1101 EXPECT_TRUE(did_request_animate_
);
1102 // The pending tree with an animation does not need to draw after animating.
1103 EXPECT_FALSE(did_request_redraw_
);
1104 EXPECT_FALSE(did_request_commit_
);
1106 did_request_animate_
= false;
1107 did_request_redraw_
= false;
1108 did_request_commit_
= false;
1110 host_impl_
->ActivateSyncTree();
1112 // When the animation activates, we should request another animation frame
1113 // to keep the animation moving.
1114 EXPECT_TRUE(did_request_animate_
);
1115 // On activation we don't need to request a redraw for the animation,
1116 // activating will draw on its own when it's ready.
1117 EXPECT_FALSE(did_request_redraw_
);
1118 EXPECT_FALSE(did_request_commit_
);
1121 TEST_F(LayerTreeHostImplTest
, AnimationSchedulingActiveTree
) {
1122 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1124 host_impl_
->active_tree()->SetRootLayer(
1125 LayerImpl::Create(host_impl_
->active_tree(), 1));
1126 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
1127 root
->SetBounds(gfx::Size(50, 50));
1128 root
->SetHasRenderSurface(true);
1130 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
1131 LayerImpl
* child
= root
->children()[0];
1132 child
->SetBounds(gfx::Size(10, 10));
1133 child
->draw_properties().visible_layer_rect
= gfx::Rect(10, 10);
1134 child
->SetDrawsContent(true);
1136 // Add a translate from 6,7 to 8,9.
1137 TransformOperations start
;
1138 start
.AppendTranslate(6.f
, 7.f
, 0.f
);
1139 TransformOperations end
;
1140 end
.AppendTranslate(8.f
, 9.f
, 0.f
);
1141 AddAnimatedTransformToLayer(child
, 4.0, start
, end
);
1143 base::TimeTicks now
= base::TimeTicks::Now();
1144 host_impl_
->WillBeginImplFrame(
1145 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, now
));
1147 EXPECT_FALSE(did_request_animate_
);
1148 EXPECT_FALSE(did_request_redraw_
);
1149 EXPECT_FALSE(did_request_commit_
);
1151 host_impl_
->ActivateAnimations();
1152 did_request_animate_
= false;
1153 did_request_redraw_
= false;
1154 did_request_commit_
= false;
1156 host_impl_
->Animate();
1158 // An animation exists on the active layer. Doing Animate() requests another
1159 // frame after the current one.
1160 EXPECT_TRUE(did_request_animate_
);
1161 // TODO(danakj): We also need to draw in the current frame if something
1162 // animated, but this is currently handled by
1163 // SchedulerStateMachine::WillAnimate.
1164 EXPECT_FALSE(did_request_redraw_
);
1165 EXPECT_FALSE(did_request_commit_
);
1168 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1169 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1170 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1173 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1174 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1175 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1177 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1178 float page_scale_factor
= 1.f
;
1180 // The impl-based pinch zoom should adjust the max scroll position.
1182 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1183 page_scale_factor
, min_page_scale
, max_page_scale
);
1184 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
1185 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1187 float page_scale_delta
= 2.f
;
1189 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1190 host_impl_
->PinchGestureBegin();
1191 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1192 host_impl_
->PinchGestureEnd();
1193 host_impl_
->ScrollEnd();
1194 EXPECT_FALSE(did_request_animate_
);
1195 EXPECT_TRUE(did_request_redraw_
);
1196 EXPECT_TRUE(did_request_commit_
);
1197 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1199 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1200 host_impl_
->ProcessScrollDeltas();
1201 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1203 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1204 scroll_layer
->MaxScrollOffset().ToString());
1207 // Scrolling after a pinch gesture should always be in local space. The
1208 // scroll deltas have the page scale factor applied.
1210 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1211 page_scale_factor
, min_page_scale
, max_page_scale
);
1212 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
1213 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1215 float page_scale_delta
= 2.f
;
1216 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1217 host_impl_
->PinchGestureBegin();
1218 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1219 host_impl_
->PinchGestureEnd();
1220 host_impl_
->ScrollEnd();
1222 gfx::Vector2d
scroll_delta(0, 10);
1223 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1224 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1225 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1226 host_impl_
->ScrollEnd();
1228 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1229 host_impl_
->ProcessScrollDeltas();
1230 EXPECT_TRUE(ScrollInfoContains(
1231 *scroll_info
.get(), scroll_layer
->id(),
1232 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
)));
1236 TEST_F(LayerTreeHostImplTest
, ViewportScrollOrder
) {
1237 LayerTreeSettings settings
= DefaultSettings();
1238 CreateHostImpl(settings
,
1239 CreateOutputSurface());
1240 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.25f
, 4.f
);
1242 const gfx::Size
content_size(1000, 1000);
1243 const gfx::Size
viewport_size(500, 500);
1244 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1246 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1247 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1250 gfx::Vector2dF(500, 500),
1251 outer_scroll_layer
->MaxScrollOffset());
1253 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1254 host_impl_
->PinchGestureBegin();
1255 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1256 host_impl_
->PinchGestureEnd();
1257 host_impl_
->ScrollEnd();
1259 // Sanity check - we're zoomed in, starting from the origin.
1261 gfx::Vector2dF(0, 0),
1262 outer_scroll_layer
->CurrentScrollOffset());
1264 gfx::Vector2dF(0, 0),
1265 inner_scroll_layer
->CurrentScrollOffset());
1267 // Scroll down - only the inner viewport should scroll.
1268 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1269 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1270 host_impl_
->ScrollEnd();
1273 gfx::Vector2dF(50, 50),
1274 inner_scroll_layer
->CurrentScrollOffset());
1276 gfx::Vector2dF(0, 0),
1277 outer_scroll_layer
->CurrentScrollOffset());
1279 // Scroll down - outer viewport should start scrolling after the inner is at
1281 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1282 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(1000.f
, 1000.f
));
1283 host_impl_
->ScrollEnd();
1286 gfx::Vector2dF(250, 250),
1287 inner_scroll_layer
->CurrentScrollOffset());
1289 gfx::Vector2dF(300, 300),
1290 outer_scroll_layer
->CurrentScrollOffset());
1293 // Tests that scrolls during a pinch gesture (i.e. "two-finger" scrolls) work
1294 // as expected. That is, scrolling during a pinch should bubble from the inner
1295 // to the outer viewport.
1296 TEST_F(LayerTreeHostImplTest
, ScrollDuringPinchGesture
) {
1297 LayerTreeSettings settings
= DefaultSettings();
1298 CreateHostImpl(settings
,
1299 CreateOutputSurface());
1300 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1302 const gfx::Size
content_size(1000, 1000);
1303 const gfx::Size
viewport_size(500, 500);
1304 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1306 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1307 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1310 gfx::Vector2dF(500, 500),
1311 outer_scroll_layer
->MaxScrollOffset());
1313 host_impl_
->ScrollBegin(gfx::Point(250, 250), InputHandler::GESTURE
);
1314 host_impl_
->PinchGestureBegin();
1316 host_impl_
->PinchGestureUpdate(2, gfx::Point(250, 250));
1318 gfx::Vector2dF(0, 0),
1319 outer_scroll_layer
->CurrentScrollOffset());
1321 gfx::Vector2dF(125, 125),
1322 inner_scroll_layer
->CurrentScrollOffset());
1324 // Needed so that the pinch is accounted for in draw properties.
1327 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(10.f
, 10.f
));
1329 gfx::Vector2dF(0, 0),
1330 outer_scroll_layer
->CurrentScrollOffset());
1332 gfx::Vector2dF(130, 130),
1333 inner_scroll_layer
->CurrentScrollOffset());
1337 host_impl_
->ScrollBy(gfx::Point(250, 250), gfx::Vector2dF(400.f
, 400.f
));
1339 gfx::Vector2dF(80, 80),
1340 outer_scroll_layer
->CurrentScrollOffset());
1342 gfx::Vector2dF(250, 250),
1343 inner_scroll_layer
->CurrentScrollOffset());
1345 host_impl_
->PinchGestureEnd();
1346 host_impl_
->ScrollEnd();
1349 // Tests the "snapping" of pinch-zoom gestures to the screen edge. That is, when
1350 // a pinch zoom is anchored within a certain margin of the screen edge, we
1351 // should assume the user means to scroll into the edge of the screen.
1352 TEST_F(LayerTreeHostImplTest
, PinchZoomSnapsToScreenEdge
) {
1353 LayerTreeSettings settings
= DefaultSettings();
1354 CreateHostImpl(settings
,
1355 CreateOutputSurface());
1356 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
1358 const gfx::Size
content_size(1000, 1000);
1359 const gfx::Size
viewport_size(500, 500);
1360 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1362 int offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
- 5;
1363 gfx::Point
anchor(viewport_size
.width() - offsetFromEdge
,
1364 viewport_size
.height() - offsetFromEdge
);
1366 // Pinch in within the margins. The scroll should stay exactly locked to the
1367 // bottom and right.
1368 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1369 host_impl_
->PinchGestureBegin();
1370 host_impl_
->PinchGestureUpdate(2, anchor
);
1371 host_impl_
->PinchGestureEnd();
1372 host_impl_
->ScrollEnd();
1375 gfx::Vector2dF(250, 250),
1376 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1379 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1380 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1381 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1383 // Pinch in within the margins. The scroll should stay exactly locked to the
1385 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1386 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1387 host_impl_
->PinchGestureBegin();
1388 host_impl_
->PinchGestureUpdate(2, anchor
);
1389 host_impl_
->PinchGestureEnd();
1390 host_impl_
->ScrollEnd();
1393 gfx::Vector2dF(0, 0),
1394 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1397 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1398 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1399 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1401 // Pinch in just outside the margin. There should be no snapping.
1402 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1403 anchor
= gfx::Point(offsetFromEdge
, offsetFromEdge
);
1404 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1405 host_impl_
->PinchGestureBegin();
1406 host_impl_
->PinchGestureUpdate(2, anchor
);
1407 host_impl_
->PinchGestureEnd();
1408 host_impl_
->ScrollEnd();
1411 gfx::Vector2dF(50, 50),
1412 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1415 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.f
);
1416 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1417 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2d());
1419 // Pinch in just outside the margin. There should be no snapping.
1420 offsetFromEdge
= Viewport::kPinchZoomSnapMarginDips
;
1421 anchor
= gfx::Point(viewport_size
.width() - offsetFromEdge
,
1422 viewport_size
.height() - offsetFromEdge
);
1423 host_impl_
->ScrollBegin(anchor
, InputHandler::GESTURE
);
1424 host_impl_
->PinchGestureBegin();
1425 host_impl_
->PinchGestureUpdate(2, anchor
);
1426 host_impl_
->PinchGestureEnd();
1427 host_impl_
->ScrollEnd();
1430 gfx::Vector2dF(200, 200),
1431 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1434 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1435 const gfx::Size
content_size(200, 200);
1436 const gfx::Size
viewport_size(100, 100);
1437 CreateBasicVirtualViewportLayers(viewport_size
, content_size
);
1439 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1440 LayerImpl
* inner_scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1442 // Zoom into the page by a 2X factor
1443 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1444 float page_scale_factor
= 2.f
;
1445 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1446 page_scale_factor
, min_page_scale
, max_page_scale
);
1447 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
1449 // Scroll by a small amount, there should be no bubbling to the outer
1451 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1452 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1453 host_impl_
->ScrollEnd();
1456 gfx::Vector2dF(5, 10),
1457 inner_scroll_layer
->CurrentScrollOffset());
1460 outer_scroll_layer
->CurrentScrollOffset());
1462 // Scroll by the inner viewport's max scroll extent, the remainder
1463 // should bubble up to the outer viewport.
1464 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1465 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(100.f
, 100.f
));
1466 host_impl_
->ScrollEnd();
1469 gfx::Vector2dF(50, 50),
1470 inner_scroll_layer
->CurrentScrollOffset());
1472 gfx::Vector2dF(5, 10),
1473 outer_scroll_layer
->CurrentScrollOffset());
1475 // Scroll by the outer viewport's max scroll extent, it should all go to the
1477 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1478 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(190.f
, 180.f
));
1479 host_impl_
->ScrollEnd();
1482 gfx::Vector2dF(100, 100),
1483 outer_scroll_layer
->CurrentScrollOffset());
1485 gfx::Vector2dF(50, 50),
1486 inner_scroll_layer
->CurrentScrollOffset());
1489 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1490 ui::LatencyInfo latency_info
;
1491 latency_info
.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0,
1493 scoped_ptr
<SwapPromise
> swap_promise(
1494 new LatencyInfoSwapPromise(latency_info
));
1496 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1497 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1498 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1499 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1500 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1501 host_impl_
->ScrollEnd();
1503 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1504 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1505 EXPECT_EQ(latency_info
.trace_id(), scroll_info
->swap_promises
[0]->TraceId());
1508 // Test that scrolls targeting a layer with a non-null scroll_parent() bubble
1509 // up to the scroll_parent, rather than the stacking parent.
1510 TEST_F(LayerTreeHostImplTest
, ScrollBubblesToScrollParent
) {
1511 LayerImpl
* viewport_scroll
=
1512 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1513 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1515 // Set up two scrolling children of the root, one of which is a scroll parent
1516 // to the other. Scrolls bubbling from the child should bubble to the parent,
1517 // not the viewport.
1520 LayerImpl
*child_clip
;
1522 scoped_ptr
<LayerImpl
> scroll_parent_clip
=
1523 LayerImpl::Create(host_impl_
->active_tree(), 6);
1524 scoped_ptr
<LayerImpl
> scroll_parent
= CreateScrollableLayer(
1525 7, gfx::Size(10, 10), scroll_parent_clip
.get());
1526 parent
= scroll_parent
.get();
1527 scroll_parent_clip
->AddChild(scroll_parent
.Pass());
1529 viewport_scroll
->AddChild(scroll_parent_clip
.Pass());
1531 scoped_ptr
<LayerImpl
> scroll_child_clip
=
1532 LayerImpl::Create(host_impl_
->active_tree(), 8);
1533 scoped_ptr
<LayerImpl
> scroll_child
= CreateScrollableLayer(
1534 9, gfx::Size(10, 10), scroll_child_clip
.get());
1535 child
= scroll_child
.get();
1536 scroll_child
->SetPosition(gfx::Point(20, 20));
1537 scroll_child_clip
->AddChild(scroll_child
.Pass());
1539 child_clip
= scroll_child_clip
.get();
1540 viewport_scroll
->AddChild(scroll_child_clip
.Pass());
1542 child_clip
->SetScrollParent(parent
);
1547 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1548 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(5, 5));
1549 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1550 host_impl_
->ScrollEnd();
1552 // The child should be fully scrolled by the first ScrollBy.
1553 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), child
->CurrentScrollOffset());
1555 // The scroll_parent should receive the bubbled up second ScrollBy.
1556 EXPECT_VECTOR_EQ(gfx::Vector2dF(2, 1), parent
->CurrentScrollOffset());
1558 // The viewport shouldn't have been scrolled at all.
1560 gfx::Vector2dF(0, 0),
1561 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1563 gfx::Vector2dF(0, 0),
1564 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1568 host_impl_
->ScrollBegin(gfx::Point(21, 21), InputHandler::GESTURE
);
1569 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(3, 4));
1570 host_impl_
->ScrollBy(gfx::Point(21, 21), gfx::Vector2d(2, 1));
1571 host_impl_
->ScrollEnd();
1573 // The first ScrollBy should scroll the parent to its extent.
1574 EXPECT_VECTOR_EQ(gfx::Vector2dF(5, 5), parent
->CurrentScrollOffset());
1576 // The viewport should now be next in bubbling order.
1578 gfx::Vector2dF(2, 1),
1579 host_impl_
->InnerViewportScrollLayer()->CurrentScrollOffset());
1581 gfx::Vector2dF(0, 0),
1582 host_impl_
->OuterViewportScrollLayer()->CurrentScrollOffset());
1587 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1588 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1589 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1592 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1593 DCHECK(scroll_layer
);
1595 float min_page_scale
= 1.f
;
1596 float max_page_scale
= 4.f
;
1598 // Basic pinch zoom in gesture
1600 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1602 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1604 float page_scale_delta
= 2.f
;
1605 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1606 host_impl_
->PinchGestureBegin();
1607 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1608 host_impl_
->PinchGestureEnd();
1609 host_impl_
->ScrollEnd();
1610 EXPECT_FALSE(did_request_animate_
);
1611 EXPECT_TRUE(did_request_redraw_
);
1612 EXPECT_TRUE(did_request_commit_
);
1614 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1615 host_impl_
->ProcessScrollDeltas();
1616 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1621 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1623 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1624 float page_scale_delta
= 10.f
;
1626 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1627 host_impl_
->PinchGestureBegin();
1628 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1629 host_impl_
->PinchGestureEnd();
1630 host_impl_
->ScrollEnd();
1632 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1633 host_impl_
->ProcessScrollDeltas();
1634 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1637 // Zoom-out clamping
1639 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1641 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1642 scroll_layer
->PullDeltaForMainThread();
1643 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1645 float page_scale_delta
= 0.1f
;
1646 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1647 host_impl_
->PinchGestureBegin();
1648 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1649 host_impl_
->PinchGestureEnd();
1650 host_impl_
->ScrollEnd();
1652 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1653 host_impl_
->ProcessScrollDeltas();
1654 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1656 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1659 // Two-finger panning should not happen based on pinch events only
1661 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1663 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1664 scroll_layer
->PullDeltaForMainThread();
1665 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1667 float page_scale_delta
= 1.f
;
1668 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1669 host_impl_
->PinchGestureBegin();
1670 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1671 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1672 host_impl_
->PinchGestureEnd();
1673 host_impl_
->ScrollEnd();
1675 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1676 host_impl_
->ProcessScrollDeltas();
1677 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1678 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1681 // Two-finger panning should work with interleaved scroll events
1683 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1685 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1686 scroll_layer
->PullDeltaForMainThread();
1687 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1689 float page_scale_delta
= 1.f
;
1690 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1691 host_impl_
->PinchGestureBegin();
1692 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1693 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1694 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1695 host_impl_
->PinchGestureEnd();
1696 host_impl_
->ScrollEnd();
1698 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1699 host_impl_
->ProcessScrollDeltas();
1700 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1701 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1702 gfx::Vector2d(-10, -10)));
1705 // Two-finger panning should work when starting fully zoomed out.
1707 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1708 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1709 scroll_layer
->PullDeltaForMainThread();
1710 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1712 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1713 host_impl_
->PinchGestureBegin();
1714 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1715 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1717 // Needed so layer transform includes page scale.
1720 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1721 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1722 host_impl_
->PinchGestureEnd();
1723 host_impl_
->ScrollEnd();
1725 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1726 host_impl_
->ProcessScrollDeltas();
1727 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1728 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1729 gfx::Vector2d(10, 10)));
1733 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1734 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1735 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1738 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1739 DCHECK(scroll_layer
);
1741 float min_page_scale
= 0.5f
;
1742 float max_page_scale
= 4.f
;
1743 base::TimeTicks start_time
= base::TimeTicks() +
1744 base::TimeDelta::FromSeconds(1);
1745 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1746 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1747 base::TimeTicks end_time
= start_time
+ duration
;
1749 BeginFrameArgs begin_frame_args
=
1750 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1752 // Non-anchor zoom-in
1754 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1756 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1758 did_request_redraw_
= false;
1759 did_request_animate_
= false;
1760 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1761 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1766 host_impl_
->ActivateSyncTree();
1767 EXPECT_FALSE(did_request_redraw_
);
1768 EXPECT_TRUE(did_request_animate_
);
1770 did_request_redraw_
= false;
1771 did_request_animate_
= false;
1772 begin_frame_args
.frame_time
= start_time
;
1773 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1774 host_impl_
->Animate();
1775 EXPECT_TRUE(did_request_redraw_
);
1776 EXPECT_TRUE(did_request_animate_
);
1777 host_impl_
->DidFinishImplFrame();
1779 did_request_redraw_
= false;
1780 did_request_animate_
= false;
1781 begin_frame_args
.frame_time
= halfway_through_animation
;
1782 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1783 host_impl_
->Animate();
1784 EXPECT_TRUE(did_request_redraw_
);
1785 EXPECT_TRUE(did_request_animate_
);
1786 host_impl_
->DidFinishImplFrame();
1788 did_request_redraw_
= false;
1789 did_request_animate_
= false;
1790 did_request_commit_
= false;
1791 begin_frame_args
.frame_time
= end_time
;
1792 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1793 host_impl_
->Animate();
1794 EXPECT_TRUE(did_request_commit_
);
1795 EXPECT_FALSE(did_request_animate_
);
1796 host_impl_
->DidFinishImplFrame();
1798 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1799 host_impl_
->ProcessScrollDeltas();
1800 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1801 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1802 gfx::Vector2d(-50, -50)));
1805 start_time
+= base::TimeDelta::FromSeconds(10);
1806 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1807 end_time
+= base::TimeDelta::FromSeconds(10);
1811 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1813 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1815 did_request_redraw_
= false;
1816 did_request_animate_
= false;
1817 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1818 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1819 gfx::Vector2d(25, 25),
1823 host_impl_
->ActivateSyncTree();
1824 EXPECT_FALSE(did_request_redraw_
);
1825 EXPECT_TRUE(did_request_animate_
);
1827 did_request_redraw_
= false;
1828 did_request_animate_
= false;
1829 begin_frame_args
.frame_time
= start_time
;
1830 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1831 host_impl_
->Animate();
1832 EXPECT_TRUE(did_request_redraw_
);
1833 EXPECT_TRUE(did_request_animate_
);
1834 host_impl_
->DidFinishImplFrame();
1836 did_request_redraw_
= false;
1837 did_request_commit_
= false;
1838 did_request_animate_
= false;
1839 begin_frame_args
.frame_time
= end_time
;
1840 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1841 host_impl_
->Animate();
1842 EXPECT_TRUE(did_request_redraw_
);
1843 EXPECT_FALSE(did_request_animate_
);
1844 EXPECT_TRUE(did_request_commit_
);
1845 host_impl_
->DidFinishImplFrame();
1847 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1848 host_impl_
->ProcessScrollDeltas();
1849 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1850 // Pushed to (0,0) via clamping against contents layer size.
1851 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
1852 gfx::Vector2d(-50, -50)));
1856 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1857 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1858 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1861 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1862 DCHECK(scroll_layer
);
1864 float min_page_scale
= 0.5f
;
1865 float max_page_scale
= 4.f
;
1866 base::TimeTicks start_time
= base::TimeTicks() +
1867 base::TimeDelta::FromSeconds(1);
1868 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1869 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1870 base::TimeTicks end_time
= start_time
+ duration
;
1872 BeginFrameArgs begin_frame_args
=
1873 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1875 // Anchor zoom with unchanged page scale should not change scroll or scale.
1877 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1879 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1881 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1882 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1887 host_impl_
->ActivateSyncTree();
1888 begin_frame_args
.frame_time
= start_time
;
1889 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1890 host_impl_
->Animate();
1891 host_impl_
->DidFinishImplFrame();
1893 begin_frame_args
.frame_time
= halfway_through_animation
;
1894 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1895 host_impl_
->Animate();
1896 EXPECT_TRUE(did_request_redraw_
);
1897 host_impl_
->DidFinishImplFrame();
1899 begin_frame_args
.frame_time
= end_time
;
1900 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1901 host_impl_
->Animate();
1902 EXPECT_TRUE(did_request_commit_
);
1903 host_impl_
->DidFinishImplFrame();
1905 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1906 host_impl_
->ProcessScrollDeltas();
1907 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1908 ExpectNone(*scroll_info
, scroll_layer
->id());
1912 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1913 host_impl_
->CreatePendingTree();
1914 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
1915 CreateScrollAndContentsLayers(
1916 host_impl_
->pending_tree(),
1917 gfx::Size(100, 100));
1918 host_impl_
->ActivateSyncTree();
1921 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1922 DCHECK(scroll_layer
);
1924 float min_page_scale
= 0.5f
;
1925 float max_page_scale
= 4.f
;
1926 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1928 host_impl_
->ActivateSyncTree();
1930 base::TimeTicks start_time
= base::TimeTicks() +
1931 base::TimeDelta::FromSeconds(1);
1932 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1933 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1934 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1935 base::TimeTicks end_time
= start_time
+ duration
;
1936 float target_scale
= 2.f
;
1938 BeginFrameArgs begin_frame_args
=
1939 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
1941 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1943 // Make sure TakePageScaleAnimation works properly.
1945 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1946 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1951 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1952 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1953 EXPECT_EQ(target_scale
, psa
->scale
);
1954 EXPECT_EQ(duration
, psa
->duration
);
1955 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1957 // Recreate the PSA. Nothing should happen here since the tree containing the
1958 // PSA hasn't been activated yet.
1959 did_request_redraw_
= false;
1960 did_request_animate_
= false;
1961 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1962 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1967 begin_frame_args
.frame_time
= halfway_through_animation
;
1968 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1969 host_impl_
->Animate();
1970 EXPECT_FALSE(did_request_animate_
);
1971 EXPECT_FALSE(did_request_redraw_
);
1972 host_impl_
->DidFinishImplFrame();
1974 // Activate the sync tree. This should cause the animation to become enabled.
1975 // It should also clear the pointer on the sync tree.
1976 host_impl_
->ActivateSyncTree();
1978 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1979 EXPECT_FALSE(did_request_redraw_
);
1980 EXPECT_TRUE(did_request_animate_
);
1982 start_time
+= base::TimeDelta::FromSeconds(10);
1983 third_through_animation
+= base::TimeDelta::FromSeconds(10);
1984 halfway_through_animation
+= base::TimeDelta::FromSeconds(10);
1985 end_time
+= base::TimeDelta::FromSeconds(10);
1987 // From here on, make sure the animation runs as normal.
1988 did_request_redraw_
= false;
1989 did_request_animate_
= false;
1990 begin_frame_args
.frame_time
= start_time
;
1991 host_impl_
->WillBeginImplFrame(begin_frame_args
);
1992 host_impl_
->Animate();
1993 EXPECT_TRUE(did_request_redraw_
);
1994 EXPECT_TRUE(did_request_animate_
);
1995 host_impl_
->DidFinishImplFrame();
1997 did_request_redraw_
= false;
1998 did_request_animate_
= false;
1999 begin_frame_args
.frame_time
= third_through_animation
;
2000 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2001 host_impl_
->Animate();
2002 EXPECT_TRUE(did_request_redraw_
);
2003 EXPECT_TRUE(did_request_animate_
);
2004 host_impl_
->DidFinishImplFrame();
2006 // Another activation shouldn't have any effect on the animation.
2007 host_impl_
->ActivateSyncTree();
2009 did_request_redraw_
= false;
2010 did_request_animate_
= false;
2011 begin_frame_args
.frame_time
= halfway_through_animation
;
2012 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2013 host_impl_
->Animate();
2014 EXPECT_TRUE(did_request_redraw_
);
2015 EXPECT_TRUE(did_request_animate_
);
2016 host_impl_
->DidFinishImplFrame();
2018 did_request_redraw_
= false;
2019 did_request_animate_
= false;
2020 did_request_commit_
= false;
2021 begin_frame_args
.frame_time
= end_time
;
2022 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2023 host_impl_
->Animate();
2024 EXPECT_TRUE(did_request_commit_
);
2025 EXPECT_FALSE(did_request_animate_
);
2026 host_impl_
->DidFinishImplFrame();
2028 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
2029 host_impl_
->ProcessScrollDeltas();
2030 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
2031 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, scroll_layer
->id(),
2032 gfx::Vector2d(-50, -50)));
2035 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
2036 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2037 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2040 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
2041 DCHECK(scroll_layer
);
2043 base::TimeTicks start_time
=
2044 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
2045 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
2046 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
2047 base::TimeTicks end_time
= start_time
+ duration
;
2049 BeginFrameArgs begin_frame_args
=
2050 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
2052 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2053 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
2055 did_complete_page_scale_animation_
= false;
2056 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
2057 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
2058 gfx::Vector2d(), false, 2.f
, duration
)));
2059 host_impl_
->ActivateSyncTree();
2060 begin_frame_args
.frame_time
= start_time
;
2061 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2062 host_impl_
->Animate();
2063 EXPECT_FALSE(did_complete_page_scale_animation_
);
2064 host_impl_
->DidFinishImplFrame();
2066 begin_frame_args
.frame_time
= halfway_through_animation
;
2067 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2068 host_impl_
->Animate();
2069 EXPECT_FALSE(did_complete_page_scale_animation_
);
2070 host_impl_
->DidFinishImplFrame();
2072 begin_frame_args
.frame_time
= end_time
;
2073 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2074 host_impl_
->Animate();
2075 EXPECT_TRUE(did_complete_page_scale_animation_
);
2076 host_impl_
->DidFinishImplFrame();
2079 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
2081 LayerTreeHostImplOverridePhysicalTime(
2082 const LayerTreeSettings
& settings
,
2083 LayerTreeHostImplClient
* client
,
2085 SharedBitmapManager
* manager
,
2086 TaskGraphRunner
* task_graph_runner
,
2087 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
2088 : LayerTreeHostImpl(settings
,
2091 rendering_stats_instrumentation
,
2097 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
2098 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
2099 fake_current_physical_time_
);
2102 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
2103 fake_current_physical_time_
= fake_now
;
2107 base::TimeTicks fake_current_physical_time_
;
2110 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
2112 void SetupLayers(LayerTreeSettings settings
) {
2113 gfx::Size
content_size(100, 100);
2115 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
2116 new LayerTreeHostImplOverridePhysicalTime(
2117 settings
, this, &proxy_
, &shared_bitmap_manager_
,
2118 &task_graph_runner_
, &stats_instrumentation_
);
2119 host_impl_
= make_scoped_ptr(host_impl_override_time
);
2120 host_impl_
->InitializeRenderer(CreateOutputSurface());
2122 SetupScrollAndContentsLayers(content_size
);
2123 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2124 host_impl_
->SetViewportSize(
2125 gfx::Size(content_size
.width() / 2, content_size
.height() / 2));
2127 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
2128 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 400,
2129 VERTICAL
, 10, 0, false, true);
2130 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
2132 LayerImpl
* scroll
= host_impl_
->InnerViewportScrollLayer();
2133 LayerImpl
* root
= scroll
->parent()->parent();
2134 scrollbar
->SetScrollLayerAndClipLayerByIds(scroll
->id(), root
->id());
2135 root
->AddChild(scrollbar
.Pass());
2137 host_impl_
->active_tree()->DidBecomeActive();
2141 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
2142 LayerTreeSettings settings
;
2143 settings
.scrollbar_animator
= animator
;
2144 settings
.scrollbar_fade_delay_ms
= 20;
2145 settings
.scrollbar_fade_duration_ms
= 20;
2147 SetupLayers(settings
);
2149 base::TimeTicks fake_now
= base::TimeTicks::Now();
2151 EXPECT_FALSE(did_request_animate_
);
2152 EXPECT_FALSE(did_request_redraw_
);
2153 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2154 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2156 // If no scroll happened during a scroll gesture, it should have no effect.
2157 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2158 host_impl_
->ScrollEnd();
2159 EXPECT_FALSE(did_request_animate_
);
2160 EXPECT_FALSE(did_request_redraw_
);
2161 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2162 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2164 // After a scroll, a scrollbar animation should be scheduled about 20ms from
2166 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2167 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2168 EXPECT_FALSE(did_request_animate_
);
2169 EXPECT_TRUE(did_request_redraw_
);
2170 did_request_redraw_
= false;
2171 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2172 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2174 host_impl_
->ScrollEnd();
2175 EXPECT_FALSE(did_request_animate_
);
2176 EXPECT_FALSE(did_request_redraw_
);
2177 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2178 requested_animation_delay_
);
2179 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2181 fake_now
+= requested_animation_delay_
;
2182 requested_animation_delay_
= base::TimeDelta();
2183 animation_task_
.Run();
2184 animation_task_
= base::Closure();
2185 EXPECT_TRUE(did_request_animate_
);
2186 did_request_animate_
= false;
2187 EXPECT_FALSE(did_request_redraw_
);
2189 // After the scrollbar animation begins, we should start getting redraws.
2190 BeginFrameArgs begin_frame_args
=
2191 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
, fake_now
);
2192 host_impl_
->WillBeginImplFrame(begin_frame_args
);
2193 host_impl_
->Animate();
2194 EXPECT_TRUE(did_request_animate_
);
2195 did_request_animate_
= false;
2196 EXPECT_TRUE(did_request_redraw_
);
2197 did_request_redraw_
= false;
2198 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2199 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2200 host_impl_
->DidFinishImplFrame();
2202 // Setting the scroll offset outside a scroll should also cause the
2203 // scrollbar to appear and to schedule a scrollbar animation.
2204 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
2205 gfx::ScrollOffset(5, 5));
2206 EXPECT_FALSE(did_request_animate_
);
2207 EXPECT_FALSE(did_request_redraw_
);
2208 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2209 requested_animation_delay_
);
2210 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2211 requested_animation_delay_
= base::TimeDelta();
2212 animation_task_
= base::Closure();
2214 // Scrollbar animation is not triggered unnecessarily.
2215 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2216 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
2217 EXPECT_FALSE(did_request_animate_
);
2218 EXPECT_TRUE(did_request_redraw_
);
2219 did_request_redraw_
= false;
2220 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2221 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2223 host_impl_
->ScrollEnd();
2224 EXPECT_FALSE(did_request_animate_
);
2225 EXPECT_FALSE(did_request_redraw_
);
2226 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
2227 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
2229 // Changing page scale triggers scrollbar animation.
2230 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
2231 host_impl_
->active_tree()->SetPageScaleOnActiveTree(1.1f
);
2232 EXPECT_FALSE(did_request_animate_
);
2233 EXPECT_FALSE(did_request_redraw_
);
2234 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
2235 requested_animation_delay_
);
2236 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
2237 requested_animation_delay_
= base::TimeDelta();
2238 animation_task_
= base::Closure();
2242 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
2243 RunTest(LayerTreeSettings::LINEAR_FADE
);
2246 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
2247 RunTest(LayerTreeSettings::THINNING
);
2250 class LayerTreeHostImplTestScrollbarOpacity
: public LayerTreeHostImplTest
{
2252 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
2253 LayerTreeSettings settings
;
2254 settings
.scrollbar_animator
= animator
;
2255 settings
.scrollbar_fade_delay_ms
= 20;
2256 settings
.scrollbar_fade_duration_ms
= 20;
2257 settings
.verify_property_trees
= true;
2258 gfx::Size
content_size(100, 100);
2260 CreateHostImpl(settings
, CreateOutputSurface());
2261 host_impl_
->CreatePendingTree();
2262 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), content_size
);
2263 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
2264 SolidColorScrollbarLayerImpl::Create(host_impl_
->pending_tree(), 400,
2265 VERTICAL
, 10, 0, false, true);
2266 LayerImpl
* scroll
= host_impl_
->pending_tree()->InnerViewportScrollLayer();
2267 LayerImpl
* root
= scroll
->parent()->parent();
2268 scrollbar
->SetScrollLayerAndClipLayerByIds(scroll
->id(), root
->id());
2269 root
->AddChild(scrollbar
.Pass());
2270 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
2271 host_impl_
->pending_tree()->BuildPropertyTreesForTesting();
2272 host_impl_
->ActivateSyncTree();
2274 LayerImpl
* scrollbar_layer
= host_impl_
->active_tree()->LayerById(400);
2276 EffectNode
* active_tree_node
=
2277 host_impl_
->active_tree()->property_trees()->effect_tree
.Node(
2278 scrollbar_layer
->effect_tree_index());
2279 EXPECT_FLOAT_EQ(scrollbar_layer
->opacity(), active_tree_node
->data
.opacity
);
2281 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
2282 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
2283 host_impl_
->ScrollEnd();
2284 host_impl_
->CreatePendingTree();
2285 EffectNode
* pending_tree_node
=
2286 host_impl_
->pending_tree()->property_trees()->effect_tree
.Node(
2287 scrollbar_layer
->effect_tree_index());
2288 EXPECT_FLOAT_EQ(1.f
, active_tree_node
->data
.opacity
);
2289 EXPECT_FLOAT_EQ(1.f
, scrollbar_layer
->opacity());
2290 EXPECT_FLOAT_EQ(0.f
, pending_tree_node
->data
.opacity
);
2291 host_impl_
->ActivateSyncTree();
2293 host_impl_
->active_tree()->property_trees()->effect_tree
.Node(
2294 scrollbar_layer
->effect_tree_index());
2295 EXPECT_FLOAT_EQ(1.f
, active_tree_node
->data
.opacity
);
2296 EXPECT_FLOAT_EQ(1.f
, scrollbar_layer
->opacity());
2300 TEST_F(LayerTreeHostImplTestScrollbarOpacity
, LinearFade
) {
2301 RunTest(LayerTreeSettings::LINEAR_FADE
);
2304 TEST_F(LayerTreeHostImplTestScrollbarOpacity
, Thinning
) {
2305 RunTest(LayerTreeSettings::THINNING
);
2308 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
2309 float device_scale_factor
) {
2310 LayerTreeSettings settings
;
2311 settings
.scrollbar_fade_delay_ms
= 500;
2312 settings
.scrollbar_fade_duration_ms
= 300;
2313 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
2315 gfx::Size
viewport_size(300, 200);
2316 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
2317 gfx::ScaleSize(viewport_size
, device_scale_factor
));
2318 gfx::Size
content_size(1000, 1000);
2320 CreateHostImpl(settings
, CreateOutputSurface());
2321 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
2322 host_impl_
->SetViewportSize(device_viewport_size
);
2324 scoped_ptr
<LayerImpl
> root
=
2325 LayerImpl::Create(host_impl_
->active_tree(), 1);
2326 root
->SetBounds(viewport_size
);
2327 root
->SetHasRenderSurface(true);
2329 scoped_ptr
<LayerImpl
> scroll
=
2330 LayerImpl::Create(host_impl_
->active_tree(), 2);
2331 scroll
->SetScrollClipLayer(root
->id());
2332 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
2333 scroll
->SetBounds(content_size
);
2334 scroll
->SetIsContainerForFixedPositionLayers(true);
2336 scoped_ptr
<LayerImpl
> contents
=
2337 LayerImpl::Create(host_impl_
->active_tree(), 3);
2338 contents
->SetDrawsContent(true);
2339 contents
->SetBounds(content_size
);
2341 // The scrollbar is on the right side.
2342 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
2343 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
2344 scrollbar
->SetDrawsContent(true);
2345 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
2346 scrollbar
->SetPosition(gfx::Point(285, 0));
2348 scroll
->AddChild(contents
.Pass());
2349 root
->AddChild(scroll
.Pass());
2350 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
2351 root
->AddChild(scrollbar
.Pass());
2353 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2354 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
2356 host_impl_
->active_tree()->DidBecomeActive();
2359 LayerImpl
* root_scroll
=
2360 host_impl_
->active_tree()->InnerViewportScrollLayer();
2361 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
2362 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
2363 static_cast<ScrollbarAnimationControllerThinning
*>(
2364 root_scroll
->scrollbar_animation_controller());
2365 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
2367 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
2368 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2370 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
2371 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2373 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2374 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2376 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
2377 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
2378 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
2380 did_request_redraw_
= false;
2381 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2382 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
2383 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2384 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
2385 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2386 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
2387 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
2390 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
2391 SetupMouseMoveAtWithDeviceScale(1.f
);
2394 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
2395 SetupMouseMoveAtWithDeviceScale(2.f
);
2398 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
2399 SetupScrollAndContentsLayers(gfx::Size(100, 100));
2400 host_impl_
->SetViewportSize(gfx::Size(50, 50));
2401 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
2404 CompositorFrameMetadata metadata
=
2405 host_impl_
->MakeCompositorFrameMetadata();
2406 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
2407 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
2408 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
2409 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2410 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2411 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2412 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2413 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2416 // Scrolling should update metadata immediately.
2417 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2418 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2419 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
2421 CompositorFrameMetadata metadata
=
2422 host_impl_
->MakeCompositorFrameMetadata();
2423 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2425 host_impl_
->ScrollEnd();
2427 CompositorFrameMetadata metadata
=
2428 host_impl_
->MakeCompositorFrameMetadata();
2429 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2432 // Root "overflow: hidden" properties should be reflected on the outer
2433 // viewport scroll layer.
2435 host_impl_
->active_tree()
2436 ->OuterViewportScrollLayer()
2437 ->set_user_scrollable_horizontal(false);
2438 CompositorFrameMetadata metadata
=
2439 host_impl_
->MakeCompositorFrameMetadata();
2440 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2441 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2443 host_impl_
->active_tree()
2444 ->OuterViewportScrollLayer()
2445 ->set_user_scrollable_vertical(false);
2446 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2447 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2448 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2451 // Re-enable scrollability and verify that overflows are no longer hidden.
2453 host_impl_
->active_tree()
2454 ->OuterViewportScrollLayer()
2455 ->set_user_scrollable_horizontal(true);
2456 host_impl_
->active_tree()
2457 ->OuterViewportScrollLayer()
2458 ->set_user_scrollable_vertical(true);
2459 CompositorFrameMetadata metadata
=
2460 host_impl_
->MakeCompositorFrameMetadata();
2461 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
2462 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2465 // Root "overflow: hidden" properties should also be reflected on the
2466 // inner viewport scroll layer.
2468 host_impl_
->active_tree()
2469 ->InnerViewportScrollLayer()
2470 ->set_user_scrollable_horizontal(false);
2471 CompositorFrameMetadata metadata
=
2472 host_impl_
->MakeCompositorFrameMetadata();
2473 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2474 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
2476 host_impl_
->active_tree()
2477 ->InnerViewportScrollLayer()
2478 ->set_user_scrollable_vertical(false);
2479 metadata
= host_impl_
->MakeCompositorFrameMetadata();
2480 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
2481 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
2484 // Page scale should update metadata correctly (shrinking only the viewport).
2485 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
2486 host_impl_
->PinchGestureBegin();
2487 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
2488 host_impl_
->PinchGestureEnd();
2489 host_impl_
->ScrollEnd();
2491 CompositorFrameMetadata metadata
=
2492 host_impl_
->MakeCompositorFrameMetadata();
2493 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2494 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
2495 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
2496 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2497 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2498 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2501 // Likewise if set from the main thread.
2502 host_impl_
->ProcessScrollDeltas();
2503 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
2504 host_impl_
->active_tree()->SetPageScaleOnActiveTree(4.f
);
2506 CompositorFrameMetadata metadata
=
2507 host_impl_
->MakeCompositorFrameMetadata();
2508 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
2509 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
2510 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
2511 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
2512 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
2513 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
2517 class DidDrawCheckLayer
: public LayerImpl
{
2519 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2520 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2523 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2524 will_draw_called_
= true;
2525 if (will_draw_returns_false_
)
2527 return LayerImpl::WillDraw(draw_mode
, provider
);
2530 void AppendQuads(RenderPass
* render_pass
,
2531 AppendQuadsData
* append_quads_data
) override
{
2532 append_quads_called_
= true;
2533 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2536 void DidDraw(ResourceProvider
* provider
) override
{
2537 did_draw_called_
= true;
2538 LayerImpl::DidDraw(provider
);
2541 bool will_draw_called() const { return will_draw_called_
; }
2542 bool append_quads_called() const { return append_quads_called_
; }
2543 bool did_draw_called() const { return did_draw_called_
; }
2545 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2547 void ClearDidDrawCheck() {
2548 will_draw_called_
= false;
2549 append_quads_called_
= false;
2550 did_draw_called_
= false;
2553 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2555 void AddCopyRequest() {
2556 ScopedPtrVector
<CopyOutputRequest
> requests
;
2558 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2559 SetHasRenderSurface(true);
2560 PassCopyRequests(&requests
);
2564 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2565 : LayerImpl(tree_impl
, id
),
2566 will_draw_returns_false_(false),
2567 will_draw_called_(false),
2568 append_quads_called_(false),
2569 did_draw_called_(false) {
2570 SetBounds(gfx::Size(10, 10));
2571 SetDrawsContent(true);
2572 draw_properties().visible_layer_rect
= gfx::Rect(0, 0, 10, 10);
2576 bool will_draw_returns_false_
;
2577 bool will_draw_called_
;
2578 bool append_quads_called_
;
2579 bool did_draw_called_
;
2582 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2583 // The root layer is always drawn, so run this test on a child layer that
2584 // will be masked out by the root layer's bounds.
2585 host_impl_
->active_tree()->SetRootLayer(
2586 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2587 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2588 host_impl_
->active_tree()->root_layer());
2590 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2591 root
->SetHasRenderSurface(true);
2592 DidDrawCheckLayer
* layer
=
2593 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2596 LayerTreeHostImpl::FrameData frame
;
2597 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2598 host_impl_
->DrawLayers(&frame
);
2599 host_impl_
->DidDrawAllLayers(frame
);
2601 EXPECT_TRUE(layer
->will_draw_called());
2602 EXPECT_TRUE(layer
->append_quads_called());
2603 EXPECT_TRUE(layer
->did_draw_called());
2606 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2609 LayerTreeHostImpl::FrameData frame
;
2611 layer
->set_will_draw_returns_false();
2612 layer
->ClearDidDrawCheck();
2614 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2615 host_impl_
->DrawLayers(&frame
);
2616 host_impl_
->DidDrawAllLayers(frame
);
2618 EXPECT_TRUE(layer
->will_draw_called());
2619 EXPECT_FALSE(layer
->append_quads_called());
2620 EXPECT_FALSE(layer
->did_draw_called());
2624 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2625 // The root layer is always drawn, so run this test on a child layer that
2626 // will be masked out by the root layer's bounds.
2627 host_impl_
->active_tree()->SetRootLayer(
2628 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2629 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2630 host_impl_
->active_tree()->root_layer());
2631 root
->SetMasksToBounds(true);
2632 root
->SetHasRenderSurface(true);
2633 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2634 DidDrawCheckLayer
* layer
=
2635 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2636 // Ensure visible_layer_rect for layer is empty.
2637 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2638 layer
->SetBounds(gfx::Size(10, 10));
2640 LayerTreeHostImpl::FrameData frame
;
2642 EXPECT_FALSE(layer
->will_draw_called());
2643 EXPECT_FALSE(layer
->did_draw_called());
2645 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
2646 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2647 host_impl_
->DrawLayers(&frame
);
2648 host_impl_
->DidDrawAllLayers(frame
);
2650 EXPECT_FALSE(layer
->will_draw_called());
2651 EXPECT_FALSE(layer
->did_draw_called());
2653 EXPECT_TRUE(layer
->visible_layer_rect().IsEmpty());
2655 // Ensure visible_layer_rect for layer is not empty
2656 layer
->SetPosition(gfx::PointF());
2658 EXPECT_FALSE(layer
->will_draw_called());
2659 EXPECT_FALSE(layer
->did_draw_called());
2661 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2662 host_impl_
->DrawLayers(&frame
);
2663 host_impl_
->DidDrawAllLayers(frame
);
2665 EXPECT_TRUE(layer
->will_draw_called());
2666 EXPECT_TRUE(layer
->did_draw_called());
2668 EXPECT_FALSE(layer
->visible_layer_rect().IsEmpty());
2671 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2672 gfx::Size
big_size(1000, 1000);
2673 host_impl_
->SetViewportSize(big_size
);
2675 host_impl_
->active_tree()->SetRootLayer(
2676 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2677 DidDrawCheckLayer
* root
=
2678 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2680 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2681 DidDrawCheckLayer
* occluded_layer
=
2682 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2684 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2685 root
->SetHasRenderSurface(true);
2686 DidDrawCheckLayer
* top_layer
=
2687 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2688 // This layer covers the occluded_layer above. Make this layer large so it can
2690 top_layer
->SetBounds(big_size
);
2691 top_layer
->SetContentsOpaque(true);
2693 LayerTreeHostImpl::FrameData frame
;
2695 EXPECT_FALSE(occluded_layer
->will_draw_called());
2696 EXPECT_FALSE(occluded_layer
->did_draw_called());
2697 EXPECT_FALSE(top_layer
->will_draw_called());
2698 EXPECT_FALSE(top_layer
->did_draw_called());
2700 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2701 host_impl_
->DrawLayers(&frame
);
2702 host_impl_
->DidDrawAllLayers(frame
);
2704 EXPECT_FALSE(occluded_layer
->will_draw_called());
2705 EXPECT_FALSE(occluded_layer
->did_draw_called());
2706 EXPECT_TRUE(top_layer
->will_draw_called());
2707 EXPECT_TRUE(top_layer
->did_draw_called());
2710 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2711 host_impl_
->active_tree()->SetRootLayer(
2712 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2713 DidDrawCheckLayer
* root
=
2714 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2716 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2717 root
->SetHasRenderSurface(true);
2718 DidDrawCheckLayer
* layer1
=
2719 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2721 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2722 DidDrawCheckLayer
* layer2
=
2723 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2725 layer1
->SetHasRenderSurface(true);
2726 layer1
->SetShouldFlattenTransform(true);
2728 EXPECT_FALSE(root
->did_draw_called());
2729 EXPECT_FALSE(layer1
->did_draw_called());
2730 EXPECT_FALSE(layer2
->did_draw_called());
2732 LayerTreeHostImpl::FrameData frame
;
2733 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2734 host_impl_
->active_tree()->root_layer());
2735 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2736 host_impl_
->DrawLayers(&frame
);
2737 host_impl_
->DidDrawAllLayers(frame
);
2739 EXPECT_TRUE(root
->did_draw_called());
2740 EXPECT_TRUE(layer1
->did_draw_called());
2741 EXPECT_TRUE(layer2
->did_draw_called());
2743 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2744 EXPECT_TRUE(layer1
->render_surface());
2747 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2749 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2752 bool had_incomplete_tile
,
2754 ResourceProvider
* resource_provider
) {
2755 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2758 had_incomplete_tile
,
2760 resource_provider
));
2763 void AppendQuads(RenderPass
* render_pass
,
2764 AppendQuadsData
* append_quads_data
) override
{
2765 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2766 if (had_incomplete_tile_
)
2767 append_quads_data
->num_incomplete_tiles
++;
2769 append_quads_data
->num_missing_tiles
++;
2773 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2776 bool had_incomplete_tile
,
2778 ResourceProvider
* resource_provider
)
2779 : DidDrawCheckLayer(tree_impl
, id
),
2780 tile_missing_(tile_missing
),
2781 had_incomplete_tile_(had_incomplete_tile
) {
2783 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2787 bool had_incomplete_tile_
;
2790 struct PrepareToDrawSuccessTestCase
{
2792 bool has_missing_tile
= false;
2793 bool has_incomplete_tile
= false;
2794 bool is_animating
= false;
2795 bool has_copy_request
= false;
2797 bool high_res_required
= false;
2799 State layer_between
;
2801 DrawResult expected_result
;
2803 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2804 : expected_result(result
) {}
2807 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2808 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2811 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2812 // 1. Animated layer first.
2813 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2814 cases
.back().layer_before
.is_animating
= true;
2815 // 2. Animated layer between.
2816 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2817 cases
.back().layer_between
.is_animating
= true;
2818 // 3. Animated layer last.
2819 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2820 cases
.back().layer_after
.is_animating
= true;
2821 // 4. Missing tile first.
2822 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2823 cases
.back().layer_before
.has_missing_tile
= true;
2824 // 5. Missing tile between.
2825 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2826 cases
.back().layer_between
.has_missing_tile
= true;
2827 // 6. Missing tile last.
2828 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2829 cases
.back().layer_after
.has_missing_tile
= true;
2830 // 7. Incomplete tile first.
2831 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2832 cases
.back().layer_before
.has_incomplete_tile
= true;
2833 // 8. Incomplete tile between.
2834 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2835 cases
.back().layer_between
.has_incomplete_tile
= true;
2836 // 9. Incomplete tile last.
2837 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2838 cases
.back().layer_after
.has_incomplete_tile
= true;
2839 // 10. Animation with missing tile.
2841 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2842 cases
.back().layer_between
.has_missing_tile
= true;
2843 cases
.back().layer_between
.is_animating
= true;
2844 // 11. Animation with incomplete tile.
2845 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2846 cases
.back().layer_between
.has_incomplete_tile
= true;
2847 cases
.back().layer_between
.is_animating
= true;
2849 // 12. High res required.
2850 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2851 cases
.back().high_res_required
= true;
2852 // 13. High res required with incomplete tile.
2854 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2855 cases
.back().high_res_required
= true;
2856 cases
.back().layer_between
.has_incomplete_tile
= true;
2857 // 14. High res required with missing tile.
2859 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2860 cases
.back().high_res_required
= true;
2861 cases
.back().layer_between
.has_missing_tile
= true;
2863 // 15. High res required is higher priority than animating missing tiles.
2865 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2866 cases
.back().high_res_required
= true;
2867 cases
.back().layer_between
.has_missing_tile
= true;
2868 cases
.back().layer_after
.has_missing_tile
= true;
2869 cases
.back().layer_after
.is_animating
= true;
2870 // 16. High res required is higher priority than animating missing tiles.
2872 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2873 cases
.back().high_res_required
= true;
2874 cases
.back().layer_between
.has_missing_tile
= true;
2875 cases
.back().layer_before
.has_missing_tile
= true;
2876 cases
.back().layer_before
.is_animating
= true;
2878 host_impl_
->active_tree()->SetRootLayer(
2879 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2880 DidDrawCheckLayer
* root
=
2881 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2882 root
->SetHasRenderSurface(true);
2884 LayerTreeHostImpl::FrameData frame
;
2885 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2886 host_impl_
->DrawLayers(&frame
);
2887 host_impl_
->DidDrawAllLayers(frame
);
2888 host_impl_
->SwapBuffers(frame
);
2890 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2891 const auto& testcase
= cases
[i
];
2892 std::vector
<LayerImpl
*> to_remove
;
2893 for (auto* child
: root
->children())
2894 to_remove
.push_back(child
);
2895 for (auto* child
: to_remove
)
2896 root
->RemoveChild(child
);
2898 std::ostringstream scope
;
2899 scope
<< "Test case: " << i
;
2900 SCOPED_TRACE(scope
.str());
2902 root
->AddChild(MissingTextureAnimatingLayer::Create(
2903 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2904 testcase
.layer_before
.has_incomplete_tile
,
2905 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2906 DidDrawCheckLayer
* before
=
2907 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2908 if (testcase
.layer_before
.has_copy_request
)
2909 before
->AddCopyRequest();
2911 root
->AddChild(MissingTextureAnimatingLayer::Create(
2912 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2913 testcase
.layer_between
.has_incomplete_tile
,
2914 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2915 DidDrawCheckLayer
* between
=
2916 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2917 if (testcase
.layer_between
.has_copy_request
)
2918 between
->AddCopyRequest();
2920 root
->AddChild(MissingTextureAnimatingLayer::Create(
2921 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2922 testcase
.layer_after
.has_incomplete_tile
,
2923 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2924 DidDrawCheckLayer
* after
=
2925 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2926 if (testcase
.layer_after
.has_copy_request
)
2927 after
->AddCopyRequest();
2929 if (testcase
.high_res_required
)
2930 host_impl_
->SetRequiresHighResToDraw();
2932 LayerTreeHostImpl::FrameData frame
;
2933 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2934 host_impl_
->DrawLayers(&frame
);
2935 host_impl_
->DidDrawAllLayers(frame
);
2936 host_impl_
->SwapBuffers(frame
);
2940 TEST_F(LayerTreeHostImplTest
,
2941 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2942 CreateHostImpl(DefaultSettings(),
2943 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2944 EXPECT_TRUE(host_impl_
->output_surface()
2946 .draw_and_swap_full_viewport_every_frame
);
2948 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2951 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2952 // 1. Animation with missing tile.
2953 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2954 cases
.back().layer_between
.has_missing_tile
= true;
2955 cases
.back().layer_between
.is_animating
= true;
2956 // 2. High res required with incomplete tile.
2957 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2958 cases
.back().high_res_required
= true;
2959 cases
.back().layer_between
.has_incomplete_tile
= true;
2960 // 3. High res required with missing tile.
2961 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2962 cases
.back().high_res_required
= true;
2963 cases
.back().layer_between
.has_missing_tile
= true;
2965 host_impl_
->active_tree()->SetRootLayer(
2966 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2967 DidDrawCheckLayer
* root
=
2968 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2969 root
->SetHasRenderSurface(true);
2971 LayerTreeHostImpl::FrameData frame
;
2972 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2973 host_impl_
->DrawLayers(&frame
);
2974 host_impl_
->DidDrawAllLayers(frame
);
2975 host_impl_
->SwapBuffers(frame
);
2977 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2978 const auto& testcase
= cases
[i
];
2979 std::vector
<LayerImpl
*> to_remove
;
2980 for (auto* child
: root
->children())
2981 to_remove
.push_back(child
);
2982 for (auto* child
: to_remove
)
2983 root
->RemoveChild(child
);
2985 std::ostringstream scope
;
2986 scope
<< "Test case: " << i
;
2987 SCOPED_TRACE(scope
.str());
2989 root
->AddChild(MissingTextureAnimatingLayer::Create(
2990 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2991 testcase
.layer_before
.has_incomplete_tile
,
2992 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2993 DidDrawCheckLayer
* before
=
2994 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2995 if (testcase
.layer_before
.has_copy_request
)
2996 before
->AddCopyRequest();
2998 root
->AddChild(MissingTextureAnimatingLayer::Create(
2999 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
3000 testcase
.layer_between
.has_incomplete_tile
,
3001 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
3002 DidDrawCheckLayer
* between
=
3003 static_cast<DidDrawCheckLayer
*>(root
->children().back());
3004 if (testcase
.layer_between
.has_copy_request
)
3005 between
->AddCopyRequest();
3007 root
->AddChild(MissingTextureAnimatingLayer::Create(
3008 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
3009 testcase
.layer_after
.has_incomplete_tile
,
3010 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
3011 DidDrawCheckLayer
* after
=
3012 static_cast<DidDrawCheckLayer
*>(root
->children().back());
3013 if (testcase
.layer_after
.has_copy_request
)
3014 after
->AddCopyRequest();
3016 if (testcase
.high_res_required
)
3017 host_impl_
->SetRequiresHighResToDraw();
3019 LayerTreeHostImpl::FrameData frame
;
3020 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
3021 host_impl_
->DrawLayers(&frame
);
3022 host_impl_
->DidDrawAllLayers(frame
);
3023 host_impl_
->SwapBuffers(frame
);
3027 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
3028 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3029 root
->SetScrollClipLayer(Layer::INVALID_ID
);
3030 root
->SetHasRenderSurface(true);
3031 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3034 // Scroll event is ignored because layer is not scrollable.
3035 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3036 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3037 EXPECT_FALSE(did_request_redraw_
);
3038 EXPECT_FALSE(did_request_commit_
);
3041 TEST_F(LayerTreeHostImplTest
, ClampingAfterActivation
) {
3042 host_impl_
->CreatePendingTree();
3043 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
3044 CreateScrollAndContentsLayers(host_impl_
->pending_tree(),
3045 gfx::Size(100, 100));
3046 host_impl_
->ActivateSyncTree();
3048 host_impl_
->CreatePendingTree();
3049 const gfx::ScrollOffset pending_scroll
= gfx::ScrollOffset(-100, -100);
3050 LayerImpl
* active_outer_layer
=
3051 host_impl_
->active_tree()->OuterViewportScrollLayer();
3052 LayerImpl
* pending_outer_layer
=
3053 host_impl_
->pending_tree()->OuterViewportScrollLayer();
3054 pending_outer_layer
->PushScrollOffsetFromMainThread(pending_scroll
);
3056 host_impl_
->ActivateSyncTree();
3057 // Scrolloffsets on the active tree will be clamped after activation.
3058 EXPECT_EQ(active_outer_layer
->CurrentScrollOffset(), gfx::ScrollOffset(0, 0));
3061 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
3063 LayerTreeHostImplTopControlsTest()
3064 // Make the clip size the same as the layer (content) size so the layer is
3066 : layer_size_(10, 10),
3067 clip_size_(layer_size_
),
3068 top_controls_height_(50) {
3069 viewport_size_
= gfx::Size(clip_size_
.width(),
3070 clip_size_
.height() + top_controls_height_
);
3073 bool CreateHostImpl(const LayerTreeSettings
& settings
,
3074 scoped_ptr
<OutputSurface
> output_surface
) override
{
3076 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
3078 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
3079 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3080 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
3085 void SetupTopControlsAndScrollLayerWithVirtualViewport(
3086 const gfx::Size
& inner_viewport_size
,
3087 const gfx::Size
& outer_viewport_size
,
3088 const gfx::Size
& scroll_layer_size
) {
3089 CreateHostImpl(settings_
, CreateOutputSurface());
3090 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3091 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
3092 host_impl_
->DidChangeTopControlsPosition();
3094 scoped_ptr
<LayerImpl
> root
=
3095 LayerImpl::Create(host_impl_
->active_tree(), 1);
3096 scoped_ptr
<LayerImpl
> root_clip
=
3097 LayerImpl::Create(host_impl_
->active_tree(), 2);
3098 scoped_ptr
<LayerImpl
> page_scale
=
3099 LayerImpl::Create(host_impl_
->active_tree(), 3);
3101 scoped_ptr
<LayerImpl
> outer_scroll
=
3102 LayerImpl::Create(host_impl_
->active_tree(), 4);
3103 scoped_ptr
<LayerImpl
> outer_clip
=
3104 LayerImpl::Create(host_impl_
->active_tree(), 5);
3106 root_clip
->SetBounds(inner_viewport_size
);
3107 root
->SetScrollClipLayer(root_clip
->id());
3108 root
->SetBounds(outer_viewport_size
);
3109 root
->SetPosition(gfx::PointF());
3110 root
->SetDrawsContent(false);
3111 root
->SetIsContainerForFixedPositionLayers(true);
3112 root_clip
->SetHasRenderSurface(true);
3113 outer_clip
->SetBounds(outer_viewport_size
);
3114 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
3115 outer_scroll
->SetBounds(scroll_layer_size
);
3116 outer_scroll
->SetPosition(gfx::PointF());
3117 outer_scroll
->SetDrawsContent(false);
3118 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
3120 int inner_viewport_scroll_layer_id
= root
->id();
3121 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
3122 int page_scale_layer_id
= page_scale
->id();
3124 outer_clip
->AddChild(outer_scroll
.Pass());
3125 root
->AddChild(outer_clip
.Pass());
3126 page_scale
->AddChild(root
.Pass());
3127 root_clip
->AddChild(page_scale
.Pass());
3129 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3130 host_impl_
->active_tree()->SetViewportLayersFromIds(
3131 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
3132 outer_viewport_scroll_layer_id
);
3134 host_impl_
->SetViewportSize(inner_viewport_size
);
3135 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3136 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
3140 gfx::Size layer_size_
;
3141 gfx::Size clip_size_
;
3142 gfx::Size viewport_size_
;
3143 float top_controls_height_
;
3145 LayerTreeSettings settings_
;
3146 }; // class LayerTreeHostImplTopControlsTest
3148 // Tests that, on a page with content the same size as the viewport, hiding
3149 // the top controls also increases the ScrollableSize (i.e. the content size).
3150 // Since the viewport got larger, the effective scrollable "content" also did.
3151 // This ensures, for one thing, that the overscroll glow is shown in the right
3153 TEST_F(LayerTreeHostImplTopControlsTest
,
3154 HidingTopControlsExpandsScrollableSize
) {
3155 SetupTopControlsAndScrollLayerWithVirtualViewport(
3156 gfx::Size(50, 50), gfx::Size(50, 50), gfx::Size(50, 50));
3158 LayerTreeImpl
* active_tree
= host_impl_
->active_tree();
3160 // Create a content layer beneath the outer viewport scroll layer.
3161 int id
= host_impl_
->OuterViewportScrollLayer()->id();
3162 host_impl_
->OuterViewportScrollLayer()->AddChild(
3163 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2));
3164 LayerImpl
* content
= active_tree
->OuterViewportScrollLayer()->children()[0];
3165 content
->SetBounds(gfx::Size(50, 50));
3169 LayerImpl
* inner_container
= active_tree
->InnerViewportContainerLayer();
3170 LayerImpl
* outer_container
= active_tree
->OuterViewportContainerLayer();
3172 // The top controls should start off showing so the viewport should be shrunk.
3173 ASSERT_EQ(gfx::Size(50, 50), inner_container
->bounds());
3174 ASSERT_EQ(gfx::Size(50, 50), outer_container
->bounds());
3176 EXPECT_EQ(gfx::SizeF(50, 50), active_tree
->ScrollableSize());
3178 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3179 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3181 host_impl_
->top_controls_manager()->ScrollBegin();
3183 // Hide the top controls by a bit, the scrollable size should increase but the
3184 // actual content bounds shouldn't.
3186 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3187 ASSERT_EQ(gfx::Size(50, 75), inner_container
->bounds());
3188 ASSERT_EQ(gfx::Size(50, 75), outer_container
->bounds());
3189 EXPECT_EQ(gfx::SizeF(50, 75), active_tree
->ScrollableSize());
3190 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3193 // Fully hide the top controls.
3195 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3196 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3197 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3198 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3199 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3202 // Scrolling additionally shouldn't have any effect.
3204 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 25.f
));
3205 ASSERT_EQ(gfx::Size(50, 100), inner_container
->bounds());
3206 ASSERT_EQ(gfx::Size(50, 100), outer_container
->bounds());
3207 EXPECT_EQ(gfx::SizeF(50, 100), active_tree
->ScrollableSize());
3208 EXPECT_EQ(gfx::SizeF(50, 50), content
->BoundsForScrolling());
3211 host_impl_
->top_controls_manager()->ScrollEnd();
3212 host_impl_
->ScrollEnd();
3215 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
3216 SetupTopControlsAndScrollLayerWithVirtualViewport(
3217 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
3220 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3221 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3223 // Make the test scroll delta a fractional amount, to verify that the
3224 // fixed container size delta is (1) non-zero, and (2) fractional, and
3225 // (3) matches the movement of the top controls.
3226 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
3227 host_impl_
->top_controls_manager()->ScrollBegin();
3228 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3229 host_impl_
->top_controls_manager()->ScrollEnd();
3231 LayerImpl
* inner_viewport_scroll_layer
=
3232 host_impl_
->active_tree()->InnerViewportScrollLayer();
3233 DCHECK(inner_viewport_scroll_layer
);
3234 host_impl_
->ScrollEnd();
3235 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3236 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3239 // In this test, the outer viewport is initially unscrollable. We test that a
3240 // scroll initiated on the inner viewport, causing the top controls to show and
3241 // thus making the outer viewport scrollable, still scrolls the outer viewport.
3242 TEST_F(LayerTreeHostImplTopControlsTest
,
3243 TopControlsOuterViewportBecomesScrollable
) {
3244 SetupTopControlsAndScrollLayerWithVirtualViewport(
3245 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
3248 LayerImpl
* inner_scroll
=
3249 host_impl_
->active_tree()->InnerViewportScrollLayer();
3250 LayerImpl
* inner_container
=
3251 host_impl_
->active_tree()->InnerViewportContainerLayer();
3252 LayerImpl
* outer_scroll
=
3253 host_impl_
->active_tree()->OuterViewportScrollLayer();
3254 LayerImpl
* outer_container
=
3255 host_impl_
->active_tree()->OuterViewportContainerLayer();
3257 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
3258 outer_scroll
->SetDrawsContent(true);
3259 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
3261 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3262 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3263 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
3265 // The entire scroll delta should have been used to hide the top controls.
3266 // The viewport layers should be resized back to their full sizes.
3267 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3268 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3269 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
3270 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
3272 // The inner viewport should be scrollable by 50px * page_scale.
3273 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
3274 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
3275 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3276 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
3278 host_impl_
->ScrollEnd();
3280 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3281 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3282 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
3284 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3286 // The entire scroll delta should have been used to show the top controls.
3287 // The outer viewport should be resized to accomodate and scrolled to the
3288 // bottom of the document to keep the viewport in place.
3289 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3290 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
3291 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
3292 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3293 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
3295 // Now when we continue scrolling, make sure the outer viewport gets scrolled
3296 // since it wasn't scrollable when the scroll began.
3297 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
3298 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3299 EXPECT_EQ(15.f
, inner_scroll
->CurrentScrollOffset().y());
3301 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
3302 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
3303 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3305 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
3306 host_impl_
->ScrollEnd();
3308 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
3309 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
3312 // Test that the fixed position container delta is appropriately adjusted
3313 // by the top controls showing/hiding and page scale doesn't affect it.
3314 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
3315 SetupTopControlsAndScrollLayerWithVirtualViewport(
3316 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
3318 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3320 float page_scale
= 1.5f
;
3321 LayerImpl
* outer_viewport_scroll_layer
=
3322 host_impl_
->active_tree()->OuterViewportScrollLayer();
3324 // Zoom in, since the fixed container is the outer viewport, the delta should
3326 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3328 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3329 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3331 // Scroll down, the top controls hiding should expand the viewport size so
3332 // the delta should be equal to the scroll distance.
3333 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
3334 host_impl_
->top_controls_manager()->ScrollBegin();
3335 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3336 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
3337 host_impl_
->top_controls_manager()->ContentTopOffset());
3338 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
3339 outer_viewport_scroll_layer
->FixedContainerSizeDelta().y());
3340 host_impl_
->ScrollEnd();
3342 // Scroll past the maximum extent. The delta shouldn't be greater than the
3343 // top controls height.
3344 host_impl_
->top_controls_manager()->ScrollBegin();
3345 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3346 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3347 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
3348 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3349 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
3350 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3351 host_impl_
->ScrollEnd();
3353 // Scroll in the direction to make the top controls show.
3354 host_impl_
->top_controls_manager()->ScrollBegin();
3355 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
3356 EXPECT_EQ(top_controls_scroll_delta
.y(),
3357 host_impl_
->top_controls_manager()->ContentTopOffset());
3359 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
3360 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
3361 host_impl_
->top_controls_manager()->ScrollEnd();
3364 // Test that if only the top controls are scrolled, we shouldn't request a
3366 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsDontTriggerCommit
) {
3367 SetupTopControlsAndScrollLayerWithVirtualViewport(
3368 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3371 // Show top controls
3372 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3374 // Scroll 25px to hide top controls
3375 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3376 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3377 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3378 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3379 EXPECT_FALSE(did_request_commit_
);
3382 // Test that if a scrollable sublayer doesn't consume the scroll,
3383 // top controls should hide when scrolling down.
3384 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
3385 gfx::Size
sub_content_size(100, 400);
3386 gfx::Size
sub_content_layer_size(100, 300);
3387 SetupTopControlsAndScrollLayerWithVirtualViewport(
3388 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
3391 // Show top controls
3392 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3394 LayerImpl
* outer_viewport_scroll_layer
=
3395 host_impl_
->active_tree()->OuterViewportScrollLayer();
3396 int id
= outer_viewport_scroll_layer
->id();
3398 scoped_ptr
<LayerImpl
> child
=
3399 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
3400 scoped_ptr
<LayerImpl
> child_clip
=
3401 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
3403 child_clip
->SetBounds(sub_content_layer_size
);
3404 child
->SetScrollClipLayer(child_clip
->id());
3405 child
->SetBounds(sub_content_size
);
3406 child
->SetPosition(gfx::PointF());
3407 child
->SetDrawsContent(true);
3408 child
->SetIsContainerForFixedPositionLayers(true);
3410 // scroll child to limit
3411 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
3412 child_clip
->AddChild(child
.Pass());
3413 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
3415 // Scroll 25px to hide top controls
3416 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3417 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3418 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3419 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3420 host_impl_
->ScrollEnd();
3422 // Top controls should be hidden
3423 EXPECT_EQ(scroll_delta
.y(),
3424 top_controls_height_
-
3425 host_impl_
->top_controls_manager()->ContentTopOffset());
3428 // Ensure setting the top controls position explicitly using the setters on the
3429 // TreeImpl correctly affects the top controls manager and viewport bounds.
3430 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
3431 CreateHostImpl(settings_
, CreateOutputSurface());
3432 SetupTopControlsAndScrollLayerWithVirtualViewport(
3433 layer_size_
, layer_size_
, layer_size_
);
3436 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3437 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3438 30.f
/ top_controls_height_
);
3439 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3440 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3441 EXPECT_FLOAT_EQ(-20.f
,
3442 host_impl_
->top_controls_manager()->ControlsTopOffset());
3444 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3445 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3446 EXPECT_FLOAT_EQ(-50.f
,
3447 host_impl_
->top_controls_manager()->ControlsTopOffset());
3449 host_impl_
->DidChangeTopControlsPosition();
3451 // Now that top controls have moved, expect the clip to resize.
3452 LayerImpl
* inner_clip_ptr
=
3453 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3454 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3457 // Test that the top_controls delta and sent delta are appropriately
3458 // applied on sync tree activation. The total top controls offset shouldn't
3459 // change after the activation.
3460 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
3461 CreateHostImpl(settings_
, CreateOutputSurface());
3462 SetupTopControlsAndScrollLayerWithVirtualViewport(
3463 layer_size_
, layer_size_
, layer_size_
);
3466 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3467 20.f
/ top_controls_height_
);
3468 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3469 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
3470 15.f
/ top_controls_height_
);
3471 host_impl_
->active_tree()
3472 ->top_controls_shown_ratio()
3473 ->PullDeltaForMainThread();
3474 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3475 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
3476 top_controls_height_
);
3478 host_impl_
->DidChangeTopControlsPosition();
3479 LayerImpl
* inner_clip_ptr
=
3480 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3481 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3482 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3484 host_impl_
->ActivateSyncTree();
3486 inner_clip_ptr
= host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3487 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3488 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3491 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
3492 top_controls_height_
);
3495 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
3496 top_controls_height_
);
3499 // Test that changing the top controls layout height is correctly applied to
3500 // the inner viewport container bounds. That is, the top controls layout
3501 // height is the amount that the inner viewport container was shrunk outside
3502 // the compositor to accommodate the top controls.
3503 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
3504 CreateHostImpl(settings_
, CreateOutputSurface());
3505 SetupTopControlsAndScrollLayerWithVirtualViewport(
3506 layer_size_
, layer_size_
, layer_size_
);
3509 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
3510 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
3512 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
3514 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
3515 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
3517 host_impl_
->DidChangeTopControlsPosition();
3518 LayerImpl
* inner_clip_ptr
=
3519 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3520 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3521 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3523 host_impl_
->sync_tree()->root_layer()->SetBounds(
3524 gfx::Size(inner_clip_ptr
->bounds().width(),
3525 inner_clip_ptr
->bounds().height() - 50.f
));
3527 host_impl_
->ActivateSyncTree();
3530 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3531 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3533 // The total bounds should remain unchanged since the bounds delta should
3534 // account for the difference between the layout height and the current
3535 // top controls offset.
3536 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3537 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), inner_clip_ptr
->bounds_delta());
3539 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
3540 host_impl_
->DidChangeTopControlsPosition();
3542 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
3543 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
3544 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3545 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), inner_clip_ptr
->bounds_delta());
3546 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
3547 inner_clip_ptr
->bounds());
3550 // Test that showing/hiding the top controls when the viewport is fully scrolled
3551 // doesn't incorrectly change the viewport offset due to clamping from changing
3553 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
3554 SetupTopControlsAndScrollLayerWithVirtualViewport(
3555 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3558 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3560 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
3561 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
3563 // Scroll the viewports to max scroll offset.
3564 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3565 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3567 gfx::ScrollOffset viewport_offset
=
3568 host_impl_
->active_tree()->TotalScrollOffset();
3569 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
3571 // Hide the top controls by 25px.
3572 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3573 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3574 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3575 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3577 // scrolling down at the max extents no longer hides the top controls
3578 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3580 // forcefully hide the top controls by 25px
3581 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3582 host_impl_
->ScrollEnd();
3584 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3585 top_controls_height_
-
3586 host_impl_
->top_controls_manager()->ContentTopOffset());
3588 inner_scroll
->ClampScrollToMaxScrollOffset();
3589 outer_scroll
->ClampScrollToMaxScrollOffset();
3591 // We should still be fully scrolled.
3592 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3593 host_impl_
->active_tree()->TotalScrollOffset());
3595 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3597 // Bring the top controls down by 25px.
3598 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3599 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3600 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3601 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3602 host_impl_
->ScrollEnd();
3604 // The viewport offset shouldn't have changed.
3605 EXPECT_EQ(viewport_offset
,
3606 host_impl_
->active_tree()->TotalScrollOffset());
3608 // Scroll the viewports to max scroll offset.
3609 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3610 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3611 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3612 host_impl_
->active_tree()->TotalScrollOffset());
3615 // Test that the top controls coming in and out maintains the same aspect ratio
3616 // between the inner and outer viewports.
3617 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3618 SetupTopControlsAndScrollLayerWithVirtualViewport(
3619 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3620 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 2.f
);
3623 EXPECT_FLOAT_EQ(top_controls_height_
,
3624 host_impl_
->top_controls_manager()->ContentTopOffset());
3626 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3627 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3628 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3629 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3630 host_impl_
->ScrollEnd();
3632 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3633 top_controls_height_
-
3634 host_impl_
->top_controls_manager()->ContentTopOffset());
3636 // Top controls were hidden by 25px so the inner viewport should have expanded
3638 LayerImpl
* outer_container
=
3639 host_impl_
->active_tree()->OuterViewportContainerLayer();
3640 LayerImpl
* inner_container
=
3641 host_impl_
->active_tree()->InnerViewportContainerLayer();
3642 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3644 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3645 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3646 inner_container
->BoundsForScrolling().height();
3647 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3648 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3650 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3653 // Test that scrolling the outer viewport affects the top controls.
3654 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3655 SetupTopControlsAndScrollLayerWithVirtualViewport(
3656 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3659 EXPECT_EQ(top_controls_height_
,
3660 host_impl_
->top_controls_manager()->ContentTopOffset());
3662 // Send a gesture scroll that will scroll the outer viewport, make sure the
3663 // top controls get scrolled.
3664 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3665 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3666 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3667 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3668 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3669 host_impl_
->CurrentlyScrollingLayer());
3670 host_impl_
->ScrollEnd();
3672 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3673 top_controls_height_
-
3674 host_impl_
->top_controls_manager()->ContentTopOffset());
3676 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3677 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3678 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3679 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3681 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3682 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3683 host_impl_
->CurrentlyScrollingLayer());
3685 host_impl_
->ScrollEnd();
3687 // Position the viewports such that the inner viewport will be scrolled.
3688 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3689 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3690 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3692 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3693 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3694 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3695 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3697 EXPECT_EQ(top_controls_height_
,
3698 host_impl_
->top_controls_manager()->ContentTopOffset());
3700 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3701 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3703 host_impl_
->ScrollEnd();
3706 TEST_F(LayerTreeHostImplTopControlsTest
,
3707 ScrollNonScrollableRootWithTopControls
) {
3708 CreateHostImpl(settings_
, CreateOutputSurface());
3709 SetupTopControlsAndScrollLayerWithVirtualViewport(
3710 layer_size_
, layer_size_
, layer_size_
);
3713 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3714 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3716 host_impl_
->top_controls_manager()->ScrollBegin();
3717 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3718 host_impl_
->top_controls_manager()->ScrollEnd();
3719 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3720 // Now that top controls have moved, expect the clip to resize.
3721 LayerImpl
* inner_clip_ptr
=
3722 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
3723 EXPECT_EQ(viewport_size_
, inner_clip_ptr
->bounds());
3725 host_impl_
->ScrollEnd();
3727 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3728 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3730 float scroll_increment_y
= -25.f
;
3731 host_impl_
->top_controls_manager()->ScrollBegin();
3732 host_impl_
->top_controls_manager()->ScrollBy(
3733 gfx::Vector2dF(0.f
, scroll_increment_y
));
3734 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3735 host_impl_
->top_controls_manager()->ContentTopOffset());
3736 // Now that top controls have moved, expect the clip to resize.
3737 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3738 viewport_size_
.height() + scroll_increment_y
),
3739 inner_clip_ptr
->bounds());
3741 host_impl_
->top_controls_manager()->ScrollBy(
3742 gfx::Vector2dF(0.f
, scroll_increment_y
));
3743 host_impl_
->top_controls_manager()->ScrollEnd();
3744 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3745 host_impl_
->top_controls_manager()->ContentTopOffset());
3746 // Now that top controls have moved, expect the clip to resize.
3747 EXPECT_EQ(clip_size_
, inner_clip_ptr
->bounds());
3749 host_impl_
->ScrollEnd();
3751 // Verify the layer is once-again non-scrollable.
3753 gfx::ScrollOffset(),
3754 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3756 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3757 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3760 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3761 // Test the configuration where a non-composited root layer is embedded in a
3762 // scrollable outer layer.
3763 gfx::Size
surface_size(10, 10);
3764 gfx::Size
contents_size(20, 20);
3766 scoped_ptr
<LayerImpl
> content_layer
=
3767 LayerImpl::Create(host_impl_
->active_tree(), 1);
3768 content_layer
->SetDrawsContent(true);
3769 content_layer
->SetPosition(gfx::PointF());
3770 content_layer
->SetBounds(contents_size
);
3772 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3773 LayerImpl::Create(host_impl_
->active_tree(), 3);
3774 scroll_clip_layer
->SetBounds(surface_size
);
3776 scoped_ptr
<LayerImpl
> scroll_layer
=
3777 LayerImpl::Create(host_impl_
->active_tree(), 2);
3778 scroll_layer
->SetScrollClipLayer(3);
3779 scroll_layer
->SetBounds(contents_size
);
3780 scroll_layer
->SetPosition(gfx::PointF());
3781 scroll_layer
->AddChild(content_layer
.Pass());
3782 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3784 scroll_clip_layer
->SetHasRenderSurface(true);
3785 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3786 host_impl_
->SetViewportSize(surface_size
);
3789 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3790 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3791 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3792 host_impl_
->ScrollEnd();
3793 EXPECT_TRUE(did_request_redraw_
);
3794 EXPECT_TRUE(did_request_commit_
);
3797 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3798 gfx::Size
surface_size(10, 10);
3799 gfx::Size
contents_size(20, 20);
3800 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3801 root
->SetBounds(surface_size
);
3802 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3803 root
->SetHasRenderSurface(true);
3804 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3805 host_impl_
->SetViewportSize(surface_size
);
3808 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3809 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3810 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3811 host_impl_
->ScrollEnd();
3812 EXPECT_TRUE(did_request_redraw_
);
3813 EXPECT_TRUE(did_request_commit_
);
3816 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3817 gfx::Size
surface_size(10, 10);
3818 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3819 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3820 root
->SetHasRenderSurface(true);
3821 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3822 host_impl_
->SetViewportSize(surface_size
);
3825 // Scroll event is ignored because the input coordinate is outside the layer
3827 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3828 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3829 EXPECT_FALSE(did_request_redraw_
);
3830 EXPECT_FALSE(did_request_commit_
);
3833 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3834 gfx::Size
surface_size(10, 10);
3835 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3836 root
->SetHasRenderSurface(true);
3837 scoped_ptr
<LayerImpl
> child
=
3838 CreateScrollableLayer(2, surface_size
, root
.get());
3839 host_impl_
->SetViewportSize(surface_size
);
3841 gfx::Transform matrix
;
3842 matrix
.RotateAboutXAxis(180.0);
3843 child
->SetTransform(matrix
);
3844 child
->SetDoubleSided(false);
3846 root
->AddChild(child
.Pass());
3847 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3850 // Scroll event is ignored because the scrollable layer is not facing the
3851 // viewer and there is nothing scrollable behind it.
3852 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3853 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3854 EXPECT_FALSE(did_request_redraw_
);
3855 EXPECT_FALSE(did_request_commit_
);
3858 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3859 gfx::Size
surface_size(10, 10);
3860 scoped_ptr
<LayerImpl
> clip_layer
=
3861 LayerImpl::Create(host_impl_
->active_tree(), 3);
3862 scoped_ptr
<LayerImpl
> content_layer
=
3863 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3864 content_layer
->SetShouldScrollOnMainThread(true);
3865 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3867 // Note: we can use the same clip layer for both since both calls to
3868 // CreateScrollableLayer() use the same surface size.
3869 scoped_ptr
<LayerImpl
> scroll_layer
=
3870 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3871 scroll_layer
->AddChild(content_layer
.Pass());
3872 clip_layer
->AddChild(scroll_layer
.Pass());
3873 clip_layer
->SetHasRenderSurface(true);
3875 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3876 host_impl_
->SetViewportSize(surface_size
);
3879 // Scrolling fails because the content layer is asking to be scrolled on the
3881 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3882 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3885 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3886 gfx::Size
viewport_size(20, 20);
3887 float page_scale
= 2.f
;
3889 SetupScrollAndContentsLayers(viewport_size
);
3891 // Setup the layers so that the outer viewport is scrollable.
3892 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3894 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3896 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3899 LayerImpl
* root_scroll
=
3900 host_impl_
->active_tree()->OuterViewportScrollLayer();
3901 LayerImpl
* inner_scroll
=
3902 host_impl_
->active_tree()->InnerViewportScrollLayer();
3903 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3905 gfx::Vector2d
scroll_delta(0, 10);
3906 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3907 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3908 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3909 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3910 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3911 host_impl_
->ScrollEnd();
3913 // Set new page scale from main thread.
3914 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
3916 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3917 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3918 expected_scroll_delta
));
3920 // The scroll range should also have been updated.
3921 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3923 // The page scale delta remains constant because the impl thread did not
3925 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3928 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3929 gfx::Size
viewport_size(20, 20);
3930 float page_scale
= 2.f
;
3932 SetupScrollAndContentsLayers(viewport_size
);
3934 // Setup the layers so that the outer viewport is scrollable.
3935 host_impl_
->active_tree()->InnerViewportScrollLayer()->parent()->SetBounds(
3937 host_impl_
->active_tree()->OuterViewportScrollLayer()->SetBounds(
3939 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3942 LayerImpl
* root_scroll
=
3943 host_impl_
->active_tree()->OuterViewportScrollLayer();
3944 LayerImpl
* inner_scroll
=
3945 host_impl_
->active_tree()->InnerViewportScrollLayer();
3946 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3948 gfx::Vector2d
scroll_delta(0, 10);
3949 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3950 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3951 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3952 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3953 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3954 host_impl_
->ScrollEnd();
3956 // Set new page scale on impl thread by pinching.
3957 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3958 host_impl_
->PinchGestureBegin();
3959 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3960 host_impl_
->PinchGestureEnd();
3961 host_impl_
->ScrollEnd();
3964 // The scroll delta is not scaled because the main thread did not scale.
3965 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3966 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
3967 expected_scroll_delta
));
3969 // The scroll range should also have been updated.
3970 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3972 // The page scale delta should match the new scale on the impl side.
3973 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3976 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3977 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 2.f
);
3978 gfx::Size
surface_size(10, 10);
3979 float default_page_scale
= 1.f
;
3980 gfx::Transform default_page_scale_matrix
;
3981 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3983 float new_page_scale
= 2.f
;
3984 gfx::Transform new_page_scale_matrix
;
3985 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3987 // Create a normal scrollable root layer and another scrollable child layer.
3988 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3989 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3990 LayerImpl
* child
= scroll
->children()[0];
3992 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3993 LayerImpl::Create(host_impl_
->active_tree(), 6);
3994 scoped_ptr
<LayerImpl
> scrollable_child
=
3995 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3996 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3997 child
->AddChild(scrollable_child_clip
.Pass());
3998 LayerImpl
* grand_child
= child
->children()[0];
4000 // Set new page scale on impl thread by pinching.
4001 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4002 host_impl_
->PinchGestureBegin();
4003 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
4004 host_impl_
->PinchGestureEnd();
4005 host_impl_
->ScrollEnd();
4008 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
4009 // the page scale delta on the root layer is applied hierarchically.
4010 LayerTreeHostImpl::FrameData frame
;
4011 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4012 host_impl_
->DrawLayers(&frame
);
4013 host_impl_
->DidDrawAllLayers(frame
);
4015 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
4016 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
4017 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
4018 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
4019 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
4020 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
4021 EXPECT_EQ(new_page_scale
,
4022 grand_child
->draw_transform().matrix().getDouble(0, 0));
4023 EXPECT_EQ(new_page_scale
,
4024 grand_child
->draw_transform().matrix().getDouble(1, 1));
4027 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
4028 SetupScrollAndContentsLayers(gfx::Size(30, 30));
4030 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
4031 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
4033 // Make the outer scroll layer scrollable.
4034 outer_scroll
->SetBounds(gfx::Size(50, 50));
4038 gfx::Vector2d
scroll_delta(0, 10);
4039 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
4040 gfx::ScrollOffset
expected_max_scroll(outer_scroll
->MaxScrollOffset());
4041 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4042 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4043 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4044 host_impl_
->ScrollEnd();
4046 float page_scale
= 2.f
;
4047 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
4052 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4053 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), inner_scroll
->id(),
4054 expected_scroll_delta
));
4056 // The scroll range should not have changed.
4057 EXPECT_EQ(outer_scroll
->MaxScrollOffset(), expected_max_scroll
);
4059 // The page scale delta remains constant because the impl thread did not
4061 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
4064 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
4065 // Scroll a child layer beyond its maximum scroll range and make sure the
4066 // parent layer is scrolled on the axis on which the child was unable to
4068 gfx::Size
surface_size(10, 10);
4069 gfx::Size
content_size(20, 20);
4070 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4071 root
->SetBounds(surface_size
);
4072 root
->SetHasRenderSurface(true);
4073 scoped_ptr
<LayerImpl
> grand_child
=
4074 CreateScrollableLayer(3, content_size
, root
.get());
4076 scoped_ptr
<LayerImpl
> child
=
4077 CreateScrollableLayer(2, content_size
, root
.get());
4078 LayerImpl
* grand_child_layer
= grand_child
.get();
4079 child
->AddChild(grand_child
.Pass());
4081 LayerImpl
* child_layer
= child
.get();
4082 root
->AddChild(child
.Pass());
4083 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4084 host_impl_
->active_tree()->DidBecomeActive();
4085 host_impl_
->SetViewportSize(surface_size
);
4086 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
4087 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
4091 gfx::Vector2d
scroll_delta(-8, -7);
4092 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4093 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4094 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4095 host_impl_
->ScrollEnd();
4097 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4098 host_impl_
->ProcessScrollDeltas();
4100 // The grand child should have scrolled up to its limit.
4101 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
4102 LayerImpl
* grand_child
= child
->children()[0];
4103 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4104 gfx::Vector2d(0, -5)));
4106 // The child should have only scrolled on the other axis.
4107 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4108 gfx::Vector2d(-3, 0)));
4112 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
4113 // Scroll a child layer beyond its maximum scroll range and make sure the
4114 // the scroll doesn't bubble up to the parent layer.
4115 gfx::Size
surface_size(20, 20);
4116 gfx::Size
viewport_size(10, 10);
4117 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
4118 root
->SetHasRenderSurface(true);
4119 scoped_ptr
<LayerImpl
> root_scrolling
=
4120 CreateScrollableLayer(2, surface_size
, root
.get());
4121 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
4123 scoped_ptr
<LayerImpl
> grand_child
=
4124 CreateScrollableLayer(4, surface_size
, root
.get());
4126 scoped_ptr
<LayerImpl
> child
=
4127 CreateScrollableLayer(3, surface_size
, root
.get());
4128 LayerImpl
* grand_child_layer
= grand_child
.get();
4129 child
->AddChild(grand_child
.Pass());
4131 LayerImpl
* child_layer
= child
.get();
4132 root_scrolling
->AddChild(child
.Pass());
4133 root
->AddChild(root_scrolling
.Pass());
4134 EXPECT_EQ(viewport_size
, root
->bounds());
4135 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4136 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4138 host_impl_
->active_tree()->DidBecomeActive();
4139 host_impl_
->SetViewportSize(viewport_size
);
4141 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4142 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4146 gfx::Vector2d
scroll_delta(0, -10);
4147 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4148 host_impl_
->ScrollBegin(gfx::Point(),
4149 InputHandler::NON_BUBBLING_GESTURE
));
4150 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4151 host_impl_
->ScrollEnd();
4153 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4154 host_impl_
->ProcessScrollDeltas();
4156 // The grand child should have scrolled up to its limit.
4158 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
4159 LayerImpl
* grand_child
= child
->children()[0];
4160 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4161 gfx::Vector2d(0, -2)));
4163 // The child should not have scrolled.
4164 ExpectNone(*scroll_info
.get(), child
->id());
4166 // The next time we scroll we should only scroll the parent.
4167 scroll_delta
= gfx::Vector2d(0, -3);
4168 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4169 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4170 InputHandler::NON_BUBBLING_GESTURE
));
4171 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4172 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4173 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
4174 host_impl_
->ScrollEnd();
4176 scroll_info
= host_impl_
->ProcessScrollDeltas();
4178 // The child should have scrolled up to its limit.
4179 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4180 gfx::Vector2d(0, -3)));
4182 // The grand child should not have scrolled.
4183 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4184 gfx::Vector2d(0, -2)));
4186 // After scrolling the parent, another scroll on the opposite direction
4187 // should still scroll the child.
4188 scroll_delta
= gfx::Vector2d(0, 7);
4189 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4190 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4191 InputHandler::NON_BUBBLING_GESTURE
));
4192 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4193 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4194 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
4195 host_impl_
->ScrollEnd();
4197 scroll_info
= host_impl_
->ProcessScrollDeltas();
4199 // The grand child should have scrolled.
4200 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4201 gfx::Vector2d(0, 5)));
4203 // The child should not have scrolled.
4204 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child
->id(),
4205 gfx::Vector2d(0, -3)));
4207 // Scrolling should be adjusted from viewport space.
4208 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
4209 host_impl_
->active_tree()->SetPageScaleOnActiveTree(2.f
);
4211 scroll_delta
= gfx::Vector2d(0, -2);
4212 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4213 host_impl_
->ScrollBegin(gfx::Point(1, 1),
4214 InputHandler::NON_BUBBLING_GESTURE
));
4215 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
4216 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4217 host_impl_
->ScrollEnd();
4219 scroll_info
= host_impl_
->ProcessScrollDeltas();
4221 // Should have scrolled by half the amount in layer space (5 - 2/2)
4222 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), grand_child
->id(),
4223 gfx::Vector2d(0, 4)));
4226 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
4227 // When we try to scroll a non-scrollable child layer, the scroll delta
4228 // should be applied to one of its ancestors if possible.
4229 gfx::Size
surface_size(10, 10);
4230 gfx::Size
content_size(20, 20);
4231 scoped_ptr
<LayerImpl
> root_clip
=
4232 LayerImpl::Create(host_impl_
->active_tree(), 3);
4233 root_clip
->SetHasRenderSurface(true);
4234 scoped_ptr
<LayerImpl
> root
=
4235 CreateScrollableLayer(1, content_size
, root_clip
.get());
4236 // Make 'root' the clip layer for child: since they have the same sizes the
4237 // child will have zero max_scroll_offset and scrolls will bubble.
4238 scoped_ptr
<LayerImpl
> child
=
4239 CreateScrollableLayer(2, content_size
, root
.get());
4240 child
->SetIsContainerForFixedPositionLayers(true);
4241 root
->SetBounds(content_size
);
4243 int root_scroll_id
= root
->id();
4244 root
->AddChild(child
.Pass());
4245 root_clip
->AddChild(root
.Pass());
4247 host_impl_
->SetViewportSize(surface_size
);
4248 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4249 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
4251 host_impl_
->active_tree()->DidBecomeActive();
4254 gfx::Vector2d
scroll_delta(0, 4);
4255 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4256 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4257 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4258 host_impl_
->ScrollEnd();
4260 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4261 host_impl_
->ProcessScrollDeltas();
4263 // Only the root scroll should have scrolled.
4264 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
4266 ScrollInfoContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
));
4270 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
4271 gfx::Size
surface_size(10, 10);
4272 scoped_ptr
<LayerImpl
> root_clip
=
4273 LayerImpl::Create(host_impl_
->active_tree(), 1);
4274 scoped_ptr
<LayerImpl
> root_scroll
=
4275 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4276 root_scroll
->SetIsContainerForFixedPositionLayers(true);
4277 root_clip
->SetHasRenderSurface(true);
4278 root_clip
->AddChild(root_scroll
.Pass());
4279 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4280 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
4282 host_impl_
->active_tree()->DidBecomeActive();
4283 host_impl_
->SetViewportSize(surface_size
);
4285 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
4288 host_impl_
->active_tree()->DetachLayerTree();
4289 scoped_ptr
<LayerImpl
> root_clip2
=
4290 LayerImpl::Create(host_impl_
->active_tree(), 3);
4291 scoped_ptr
<LayerImpl
> root_scroll2
=
4292 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
4293 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
4294 root_clip2
->AddChild(root_scroll2
.Pass());
4295 root_clip2
->SetHasRenderSurface(true);
4296 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
4297 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
4299 host_impl_
->active_tree()->DidBecomeActive();
4301 // Scrolling should still work even though we did not draw yet.
4302 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4303 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4306 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
4307 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4309 // Rotate the root layer 90 degrees counter-clockwise about its center.
4310 gfx::Transform rotate_transform
;
4311 rotate_transform
.Rotate(-90.0);
4312 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
4314 gfx::Size
surface_size(50, 50);
4315 host_impl_
->SetViewportSize(surface_size
);
4318 // Scroll to the right in screen coordinates with a gesture.
4319 gfx::Vector2d
gesture_scroll_delta(10, 0);
4320 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4321 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4322 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4323 host_impl_
->ScrollEnd();
4325 // The layer should have scrolled down in its local coordinates.
4326 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4327 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4328 gfx::Vector2d(0, gesture_scroll_delta
.x())));
4330 // Reset and scroll down with the wheel.
4331 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4332 gfx::Vector2d
wheel_scroll_delta(0, 10);
4333 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4334 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4335 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4336 host_impl_
->ScrollEnd();
4338 // The layer should have scrolled down in its local coordinates.
4339 scroll_info
= host_impl_
->ProcessScrollDeltas();
4340 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4341 wheel_scroll_delta
));
4344 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
4345 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4346 int child_clip_layer_id
= 6;
4347 int child_layer_id
= 7;
4348 float child_layer_angle
= -20.f
;
4350 // Create a child layer that is rotated to a non-axis-aligned angle.
4351 scoped_ptr
<LayerImpl
> clip_layer
=
4352 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4353 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4354 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4355 gfx::Transform rotate_transform
;
4356 rotate_transform
.Translate(-50.0, -50.0);
4357 rotate_transform
.Rotate(child_layer_angle
);
4358 rotate_transform
.Translate(50.0, 50.0);
4359 clip_layer
->SetTransform(rotate_transform
);
4361 // Only allow vertical scrolling.
4362 clip_layer
->SetBounds(
4363 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
4364 // The rotation depends on the layer's transform origin, and the child layer
4365 // is a different size than the clip, so make sure the clip layer's origin
4366 // lines up over the child.
4367 clip_layer
->SetTransformOrigin(gfx::Point3F(
4368 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
4369 LayerImpl
* child_ptr
= child
.get();
4370 clip_layer
->AddChild(child
.Pass());
4371 scroll_layer
->AddChild(clip_layer
.Pass());
4373 gfx::Size
surface_size(50, 50);
4374 host_impl_
->SetViewportSize(surface_size
);
4377 // Scroll down in screen coordinates with a gesture.
4378 gfx::Vector2d
gesture_scroll_delta(0, 10);
4379 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4380 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4381 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4382 host_impl_
->ScrollEnd();
4384 // The child layer should have scrolled down in its local coordinates an
4385 // amount proportional to the angle between it and the input scroll delta.
4386 gfx::Vector2d
expected_scroll_delta(
4387 0, gesture_scroll_delta
.y() *
4388 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
4389 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4390 host_impl_
->ProcessScrollDeltas();
4391 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4392 expected_scroll_delta
));
4394 // The root scroll layer should not have scrolled, because the input delta
4395 // was close to the layer's axis of movement.
4396 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4399 // Now reset and scroll the same amount horizontally.
4400 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4401 gfx::Vector2d
gesture_scroll_delta(10, 0);
4402 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4403 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
4404 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
4405 host_impl_
->ScrollEnd();
4407 // The child layer should have scrolled down in its local coordinates an
4408 // amount proportional to the angle between it and the input scroll delta.
4409 gfx::Vector2d
expected_scroll_delta(
4410 0, -gesture_scroll_delta
.x() *
4411 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
4412 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
4413 host_impl_
->ProcessScrollDeltas();
4414 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4415 expected_scroll_delta
));
4417 // The root scroll layer should have scrolled more, since the input scroll
4418 // delta was mostly orthogonal to the child layer's vertical scroll axis.
4419 gfx::Vector2d
expected_root_scroll_delta(
4420 gesture_scroll_delta
.x() *
4421 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
4423 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4424 expected_root_scroll_delta
));
4428 TEST_F(LayerTreeHostImplTest
, ScrollPerspectiveTransformedLayer
) {
4429 // When scrolling an element with perspective, the distance scrolled
4430 // depends on the point at which the scroll begins.
4431 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4432 int child_clip_layer_id
= 6;
4433 int child_layer_id
= 7;
4435 // Create a child layer that is rotated on its x axis, with perspective.
4436 scoped_ptr
<LayerImpl
> clip_layer
=
4437 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
4438 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
4439 child_layer_id
, scroll_layer
->bounds(), clip_layer
.get());
4440 LayerImpl
* child_ptr
= child
.get();
4441 gfx::Transform perspective_transform
;
4442 perspective_transform
.Translate(-50.0, -50.0);
4443 perspective_transform
.ApplyPerspectiveDepth(20);
4444 perspective_transform
.RotateAboutXAxis(45);
4445 perspective_transform
.Translate(50.0, 50.0);
4446 clip_layer
->SetTransform(perspective_transform
);
4448 clip_layer
->SetBounds(gfx::Size(child_ptr
->bounds().width() / 2,
4449 child_ptr
->bounds().height() / 2));
4450 // The transform depends on the layer's transform origin, and the child layer
4451 // is a different size than the clip, so make sure the clip layer's origin
4452 // lines up over the child.
4453 clip_layer
->SetTransformOrigin(gfx::Point3F(
4454 clip_layer
->bounds().width(), clip_layer
->bounds().height(), 0.f
));
4455 clip_layer
->AddChild(child
.Pass());
4456 scroll_layer
->AddChild(clip_layer
.Pass());
4458 gfx::Size
surface_size(50, 50);
4459 host_impl_
->SetViewportSize(surface_size
);
4461 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
4463 gfx::Vector2d gesture_scroll_deltas
[4];
4464 gesture_scroll_deltas
[0] = gfx::Vector2d(4, 10);
4465 gesture_scroll_deltas
[1] = gfx::Vector2d(4, 10);
4466 gesture_scroll_deltas
[2] = gfx::Vector2d(10, 0);
4467 gesture_scroll_deltas
[3] = gfx::Vector2d(10, 0);
4469 gfx::Vector2d expected_scroll_deltas
[4];
4470 // Perspective affects the vertical delta by a different
4471 // amount depending on the vertical position of the |viewport_point|.
4472 expected_scroll_deltas
[0] = gfx::Vector2d(2, 8);
4473 expected_scroll_deltas
[1] = gfx::Vector2d(1, 4);
4474 // Deltas which start with the same vertical position of the
4475 // |viewport_point| are subject to identical perspective effects.
4476 expected_scroll_deltas
[2] = gfx::Vector2d(4, 0);
4477 expected_scroll_deltas
[3] = gfx::Vector2d(4, 0);
4479 gfx::Point
viewport_point(1, 1);
4481 // Scroll in screen coordinates with a gesture. Each scroll starts
4482 // where the previous scroll ended, but the scroll position is reset
4484 for (int i
= 0; i
< 4; ++i
) {
4485 child_ptr
->SetScrollDelta(gfx::Vector2dF());
4487 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4488 host_impl_
->ScrollBegin(viewport_point
, InputHandler::GESTURE
));
4489 host_impl_
->ScrollBy(viewport_point
, gesture_scroll_deltas
[i
]);
4490 viewport_point
+= gesture_scroll_deltas
[i
];
4491 host_impl_
->ScrollEnd();
4493 scroll_info
= host_impl_
->ProcessScrollDeltas();
4494 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), child_layer_id
,
4495 expected_scroll_deltas
[i
]));
4497 // The root scroll layer should not have scrolled, because the input delta
4498 // was close to the layer's axis of movement.
4499 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
4503 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
4504 LayerImpl
* scroll_layer
=
4505 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4507 // Scale the layer to twice its normal size.
4509 gfx::Transform scale_transform
;
4510 scale_transform
.Scale(scale
, scale
);
4511 scroll_layer
->SetTransform(scale_transform
);
4513 gfx::Size
surface_size(50, 50);
4514 host_impl_
->SetViewportSize(surface_size
);
4517 // Scroll down in screen coordinates with a gesture.
4518 gfx::Vector2d
scroll_delta(0, 10);
4519 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4520 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4521 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4522 host_impl_
->ScrollEnd();
4524 // The layer should have scrolled down in its local coordinates, but half the
4526 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
4527 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4528 gfx::Vector2d(0, scroll_delta
.y() / scale
)));
4530 // Reset and scroll down with the wheel.
4531 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
4532 gfx::Vector2d
wheel_scroll_delta(0, 10);
4533 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4534 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4535 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
4536 host_impl_
->ScrollEnd();
4538 // It should apply the scale factor to the scroll delta for the wheel event.
4539 scroll_info
= host_impl_
->ProcessScrollDeltas();
4540 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), scroll_layer
->id(),
4541 wheel_scroll_delta
));
4544 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
4548 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
4549 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
4550 gfx::Size(width
* scale
- 1, height
* scale
));
4551 host_impl_
->SetDeviceScaleFactor(scale
);
4552 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4554 LayerImpl
* inner_viewport_scroll_layer
=
4555 host_impl_
->active_tree()->InnerViewportScrollLayer();
4556 EXPECT_EQ(gfx::ScrollOffset(0, 0),
4557 inner_viewport_scroll_layer
->MaxScrollOffset());
4560 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
4562 TestScrollOffsetDelegate()
4563 : page_scale_factor_(0.f
),
4564 min_page_scale_factor_(-1.f
),
4565 max_page_scale_factor_(-1.f
) {}
4567 ~TestScrollOffsetDelegate() override
{}
4569 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
4570 const gfx::ScrollOffset
& max_scroll_offset
,
4571 const gfx::SizeF
& scrollable_size
,
4572 float page_scale_factor
,
4573 float min_page_scale_factor
,
4574 float max_page_scale_factor
) override
{
4575 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
4576 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
4577 last_set_scroll_offset_
= total_scroll_offset
;
4578 max_scroll_offset_
= max_scroll_offset
;
4579 scrollable_size_
= scrollable_size
;
4580 page_scale_factor_
= page_scale_factor
;
4581 min_page_scale_factor_
= min_page_scale_factor
;
4582 max_page_scale_factor_
= max_page_scale_factor
;
4585 gfx::ScrollOffset
last_set_scroll_offset() {
4586 return last_set_scroll_offset_
;
4589 gfx::ScrollOffset
max_scroll_offset() const {
4590 return max_scroll_offset_
;
4593 gfx::SizeF
scrollable_size() const {
4594 return scrollable_size_
;
4597 float page_scale_factor() const {
4598 return page_scale_factor_
;
4601 float min_page_scale_factor() const {
4602 return min_page_scale_factor_
;
4605 float max_page_scale_factor() const {
4606 return max_page_scale_factor_
;
4610 gfx::ScrollOffset last_set_scroll_offset_
;
4611 gfx::ScrollOffset max_scroll_offset_
;
4612 gfx::SizeF scrollable_size_
;
4613 float page_scale_factor_
;
4614 float min_page_scale_factor_
;
4615 float max_page_scale_factor_
;
4618 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4619 TestScrollOffsetDelegate scroll_delegate
;
4620 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4621 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4622 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4623 clip_layer
->SetBounds(gfx::Size(10, 20));
4625 // Setting the delegate results in the current scroll offset being set.
4626 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4627 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4628 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4629 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4630 EXPECT_EQ(initial_scroll_delta
.ToString(),
4631 scroll_delegate
.last_set_scroll_offset().ToString());
4633 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4634 // page_scale_factor and {min|max}_page_scale_factor being set.
4635 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4636 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4637 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4638 EXPECT_EQ(1.f
, scroll_delegate
.min_page_scale_factor());
4639 EXPECT_EQ(1.f
, scroll_delegate
.max_page_scale_factor());
4641 // Put a page scale on the tree.
4642 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4643 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4644 EXPECT_EQ(1.f
, scroll_delegate
.min_page_scale_factor());
4645 EXPECT_EQ(1.f
, scroll_delegate
.max_page_scale_factor());
4646 // Activation will update the delegate.
4647 host_impl_
->ActivateSyncTree();
4648 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4649 EXPECT_EQ(.5f
, scroll_delegate
.min_page_scale_factor());
4650 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4652 // Reset the page scale for the rest of the test.
4653 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4654 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4655 EXPECT_EQ(.5f
, scroll_delegate
.min_page_scale_factor());
4656 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4658 // Animating page scale can change the root offset, so it should update the
4660 host_impl_
->Animate();
4661 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4662 EXPECT_EQ(.5f
, scroll_delegate
.min_page_scale_factor());
4663 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4665 // The pinch gesture doesn't put the delegate into a state where the scroll
4666 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4668 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4669 host_impl_
->PinchGestureBegin();
4670 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4671 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4672 host_impl_
->PinchGestureEnd();
4673 host_impl_
->ScrollEnd();
4675 // Scrolling should be relative to the offset as given by the delegate.
4676 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4677 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4679 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4680 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4681 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4683 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4684 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4685 scroll_delegate
.last_set_scroll_offset());
4687 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4688 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4689 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4690 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4691 scroll_delegate
.last_set_scroll_offset());
4692 host_impl_
->ScrollEnd();
4693 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(gfx::ScrollOffset());
4695 // Forces a full tree synchronization and ensures that the scroll delegate
4696 // sees the correct size of the new tree.
4697 gfx::Size
new_size(42, 24);
4698 host_impl_
->CreatePendingTree();
4699 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 1.f
);
4700 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4701 host_impl_
->ActivateSyncTree();
4702 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4704 // Un-setting the delegate should propagate the delegate's current offset to
4705 // the root scrollable layer.
4706 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4707 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
4708 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4710 EXPECT_EQ(current_offset
.ToString(),
4711 scroll_layer
->CurrentScrollOffset().ToString());
4714 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4715 const gfx::Transform target_space_transform
=
4716 layer
->draw_properties().target_space_transform
;
4717 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4718 gfx::Point translated_point
;
4719 target_space_transform
.TransformPoint(&translated_point
);
4720 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4721 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4724 TEST_F(LayerTreeHostImplTest
,
4725 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4726 TestScrollOffsetDelegate scroll_delegate
;
4727 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4728 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4729 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4730 clip_layer
->SetBounds(gfx::Size(10, 20));
4731 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4733 // Draw first frame to clear any pending draws and check scroll.
4735 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4736 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4738 // Set external scroll delta on delegate and notify LayerTreeHost.
4739 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4740 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(scroll_offset
);
4742 // Check scroll delta reflected in layer.
4743 LayerTreeHostImpl::FrameData frame
;
4744 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4745 host_impl_
->DrawLayers(&frame
);
4746 host_impl_
->DidDrawAllLayers(frame
);
4747 EXPECT_FALSE(frame
.has_no_damage
);
4748 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4750 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4753 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4754 InputHandlerScrollResult scroll_result
;
4755 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4756 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4757 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4759 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4761 // In-bounds scrolling does not affect overscroll.
4762 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4763 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4764 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4765 EXPECT_TRUE(scroll_result
.did_scroll
);
4766 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4767 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4768 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4770 // Overscroll events are reflected immediately.
4771 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4772 EXPECT_TRUE(scroll_result
.did_scroll
);
4773 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4774 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4775 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4776 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4777 host_impl_
->accumulated_root_overscroll());
4779 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4780 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4781 EXPECT_TRUE(scroll_result
.did_scroll
);
4782 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4783 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4784 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4785 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4786 host_impl_
->accumulated_root_overscroll());
4788 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4789 EXPECT_FALSE(scroll_result
.did_scroll
);
4790 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4791 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4792 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4793 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4794 host_impl_
->accumulated_root_overscroll());
4796 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4797 EXPECT_TRUE(scroll_result
.did_scroll
);
4798 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4799 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4800 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4801 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4802 host_impl_
->accumulated_root_overscroll());
4804 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4805 EXPECT_TRUE(scroll_result
.did_scroll
);
4806 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4807 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4808 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4809 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4810 host_impl_
->accumulated_root_overscroll());
4812 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4813 EXPECT_TRUE(scroll_result
.did_scroll
);
4814 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4815 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4816 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4817 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4818 host_impl_
->accumulated_root_overscroll());
4820 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4821 EXPECT_TRUE(scroll_result
.did_scroll
);
4822 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4823 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4824 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4825 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4826 host_impl_
->accumulated_root_overscroll());
4828 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4829 // as no scroll occurs.
4830 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4831 EXPECT_FALSE(scroll_result
.did_scroll
);
4832 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4833 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4834 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4835 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4836 host_impl_
->accumulated_root_overscroll());
4838 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4839 EXPECT_FALSE(scroll_result
.did_scroll
);
4840 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4841 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4842 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4843 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4844 host_impl_
->accumulated_root_overscroll());
4846 // Overscroll resets on valid scroll.
4847 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4848 EXPECT_TRUE(scroll_result
.did_scroll
);
4849 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4850 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4851 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4852 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4853 host_impl_
->accumulated_root_overscroll());
4855 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4856 EXPECT_TRUE(scroll_result
.did_scroll
);
4857 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4858 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4859 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4860 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4861 host_impl_
->accumulated_root_overscroll());
4863 host_impl_
->ScrollEnd();
4867 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4868 // Scroll child layers beyond their maximum scroll range and make sure root
4869 // overscroll does not accumulate.
4870 InputHandlerScrollResult scroll_result
;
4871 gfx::Size
surface_size(10, 10);
4872 scoped_ptr
<LayerImpl
> root_clip
=
4873 LayerImpl::Create(host_impl_
->active_tree(), 4);
4874 root_clip
->SetHasRenderSurface(true);
4876 scoped_ptr
<LayerImpl
> root
=
4877 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4879 scoped_ptr
<LayerImpl
> grand_child
=
4880 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4882 scoped_ptr
<LayerImpl
> child
=
4883 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4884 LayerImpl
* grand_child_layer
= grand_child
.get();
4885 child
->AddChild(grand_child
.Pass());
4887 LayerImpl
* child_layer
= child
.get();
4888 root
->AddChild(child
.Pass());
4889 root_clip
->AddChild(root
.Pass());
4890 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4891 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4892 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4893 host_impl_
->active_tree()->DidBecomeActive();
4894 host_impl_
->SetViewportSize(surface_size
);
4897 gfx::Vector2d
scroll_delta(0, -10);
4898 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4899 host_impl_
->ScrollBegin(gfx::Point(),
4900 InputHandler::NON_BUBBLING_GESTURE
));
4901 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4902 EXPECT_TRUE(scroll_result
.did_scroll
);
4903 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4904 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4905 host_impl_
->ScrollEnd();
4907 // The next time we scroll we should only scroll the parent, but overscroll
4908 // should still not reach the root layer.
4909 scroll_delta
= gfx::Vector2d(0, -30);
4910 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4911 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4912 InputHandler::NON_BUBBLING_GESTURE
));
4913 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4914 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4915 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4916 EXPECT_TRUE(scroll_result
.did_scroll
);
4917 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4918 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4919 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4920 host_impl_
->ScrollEnd();
4922 // After scrolling the parent, another scroll on the opposite direction
4923 // should scroll the child.
4924 scroll_delta
= gfx::Vector2d(0, 70);
4925 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4926 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4927 InputHandler::NON_BUBBLING_GESTURE
));
4928 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4929 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4930 EXPECT_TRUE(scroll_result
.did_scroll
);
4931 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4932 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4933 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4934 host_impl_
->ScrollEnd();
4938 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4939 // When we try to scroll a non-scrollable child layer, the scroll delta
4940 // should be applied to one of its ancestors if possible. Overscroll should
4941 // be reflected only when it has bubbled up to the root scrolling layer.
4942 InputHandlerScrollResult scroll_result
;
4943 SetupScrollAndContentsLayers(gfx::Size(20, 20));
4946 gfx::Vector2d
scroll_delta(0, 8);
4947 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4948 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4949 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4950 EXPECT_TRUE(scroll_result
.did_scroll
);
4951 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4952 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4953 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4954 EXPECT_TRUE(scroll_result
.did_scroll
);
4955 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4956 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4957 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4958 EXPECT_FALSE(scroll_result
.did_scroll
);
4959 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4960 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4961 host_impl_
->ScrollEnd();
4965 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4966 InputHandlerScrollResult scroll_result
;
4967 LayerTreeSettings settings
;
4968 CreateHostImpl(settings
, CreateOutputSurface());
4970 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4971 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4972 clip_layer
->SetBounds(gfx::Size(50, 50));
4973 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4974 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4976 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4978 // Even though the layer can't scroll the overscroll still happens.
4979 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4980 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4981 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4982 EXPECT_FALSE(scroll_result
.did_scroll
);
4983 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4984 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4987 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4988 InputHandlerScrollResult scroll_result
;
4989 SetupScrollAndContentsLayers(gfx::Size(200, 200));
4993 // Edge glow effect should be applicable only upon reaching Edges
4994 // of the content. unnecessary glow effect calls shouldn't be
4995 // called while scrolling up without reaching the edge of the content.
4996 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4997 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4998 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4999 EXPECT_TRUE(scroll_result
.did_scroll
);
5000 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
5001 EXPECT_EQ(gfx::Vector2dF().ToString(),
5002 host_impl_
->accumulated_root_overscroll().ToString());
5004 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
5005 EXPECT_TRUE(scroll_result
.did_scroll
);
5006 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
5007 EXPECT_EQ(gfx::Vector2dF().ToString(),
5008 host_impl_
->accumulated_root_overscroll().ToString());
5009 host_impl_
->ScrollEnd();
5010 // unusedrootDelta should be subtracted from applied delta so that
5011 // unwanted glow effect calls are not called.
5012 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
5013 host_impl_
->ScrollBegin(gfx::Point(0, 0),
5014 InputHandler::NON_BUBBLING_GESTURE
));
5015 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
5016 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
5017 EXPECT_TRUE(scroll_result
.did_scroll
);
5018 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
5019 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
5020 host_impl_
->accumulated_root_overscroll().ToString());
5023 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
5024 EXPECT_FALSE(scroll_result
.did_scroll
);
5025 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
5026 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
5027 host_impl_
->accumulated_root_overscroll().ToString());
5028 host_impl_
->ScrollEnd();
5029 // TestCase to check kEpsilon, which prevents minute values to trigger
5030 // gloweffect without reaching edge.
5031 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
5032 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
5034 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
5035 EXPECT_FALSE(scroll_result
.did_scroll
);
5036 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
5037 EXPECT_EQ(gfx::Vector2dF().ToString(),
5038 host_impl_
->accumulated_root_overscroll().ToString());
5039 host_impl_
->ScrollEnd();
5043 class BlendStateCheckLayer
: public LayerImpl
{
5045 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
5047 ResourceProvider
* resource_provider
) {
5048 return make_scoped_ptr(
5049 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
5052 void AppendQuads(RenderPass
* render_pass
,
5053 AppendQuadsData
* append_quads_data
) override
{
5054 quads_appended_
= true;
5056 gfx::Rect opaque_rect
;
5057 if (contents_opaque())
5058 opaque_rect
= quad_rect_
;
5060 opaque_rect
= opaque_content_rect_
;
5061 gfx::Rect visible_quad_rect
= quad_rect_
;
5063 SharedQuadState
* shared_quad_state
=
5064 render_pass
->CreateAndAppendSharedQuadState();
5065 PopulateSharedQuadState(shared_quad_state
);
5067 TileDrawQuad
* test_blending_draw_quad
=
5068 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
5069 test_blending_draw_quad
->SetNew(shared_quad_state
,
5074 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
5078 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
5079 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
5080 EXPECT_EQ(has_render_surface_
, !!render_surface());
5083 void SetExpectation(bool blend
, bool has_render_surface
) {
5085 has_render_surface_
= has_render_surface
;
5086 quads_appended_
= false;
5089 bool quads_appended() const { return quads_appended_
; }
5091 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
5092 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
5093 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
5094 opaque_content_rect_
= rect
;
5098 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
5100 ResourceProvider
* resource_provider
)
5101 : LayerImpl(tree_impl
, id
),
5103 has_render_surface_(false),
5104 quads_appended_(false),
5105 quad_rect_(5, 5, 5, 5),
5106 quad_visible_rect_(5, 5, 5, 5),
5107 resource_id_(resource_provider
->CreateResource(
5110 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
5112 resource_provider
->AllocateForTesting(resource_id_
);
5113 SetBounds(gfx::Size(10, 10));
5114 SetDrawsContent(true);
5118 bool has_render_surface_
;
5119 bool quads_appended_
;
5120 gfx::Rect quad_rect_
;
5121 gfx::Rect opaque_content_rect_
;
5122 gfx::Rect quad_visible_rect_
;
5123 ResourceId resource_id_
;
5126 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
5128 scoped_ptr
<LayerImpl
> root
=
5129 LayerImpl::Create(host_impl_
->active_tree(), 1);
5130 root
->SetBounds(gfx::Size(10, 10));
5131 root
->SetDrawsContent(false);
5132 root
->SetHasRenderSurface(true);
5133 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5135 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5138 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5140 host_impl_
->resource_provider()));
5141 BlendStateCheckLayer
* layer1
=
5142 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
5143 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
5145 LayerTreeHostImpl::FrameData frame
;
5147 // Opaque layer, drawn without blending.
5148 layer1
->SetContentsOpaque(true);
5149 layer1
->SetExpectation(false, false);
5150 layer1
->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 host_impl_
->DidDrawAllLayers(frame
);
5156 // Layer with translucent content and painting, so drawn with blending.
5157 layer1
->SetContentsOpaque(false);
5158 layer1
->SetExpectation(true, false);
5159 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5160 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5161 host_impl_
->DrawLayers(&frame
);
5162 EXPECT_TRUE(layer1
->quads_appended());
5163 host_impl_
->DidDrawAllLayers(frame
);
5165 // Layer with translucent opacity, drawn with blending.
5166 layer1
->SetContentsOpaque(true);
5167 layer1
->SetOpacity(0.5f
);
5168 layer1
->SetExpectation(true, false);
5169 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5170 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5171 host_impl_
->DrawLayers(&frame
);
5172 EXPECT_TRUE(layer1
->quads_appended());
5173 host_impl_
->DidDrawAllLayers(frame
);
5175 // Layer with translucent opacity and painting, drawn with blending.
5176 layer1
->SetContentsOpaque(true);
5177 layer1
->SetOpacity(0.5f
);
5178 layer1
->SetExpectation(true, false);
5179 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5180 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5181 host_impl_
->DrawLayers(&frame
);
5182 EXPECT_TRUE(layer1
->quads_appended());
5183 host_impl_
->DidDrawAllLayers(frame
);
5186 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5188 host_impl_
->resource_provider()));
5189 BlendStateCheckLayer
* layer2
=
5190 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
5191 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
5193 // 2 opaque layers, drawn without blending.
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(1.f
);
5200 layer2
->SetExpectation(false, 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 // Parent layer with translucent content, drawn with blending.
5209 // Child layer with opaque content, drawn without blending.
5210 layer1
->SetContentsOpaque(false);
5211 layer1
->SetExpectation(true, false);
5212 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5213 layer2
->SetExpectation(false, false);
5214 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5215 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5216 host_impl_
->DrawLayers(&frame
);
5217 EXPECT_TRUE(layer1
->quads_appended());
5218 EXPECT_TRUE(layer2
->quads_appended());
5219 host_impl_
->DidDrawAllLayers(frame
);
5221 // Parent layer with translucent content but opaque painting, drawn without
5223 // Child layer with opaque content, drawn without blending.
5224 layer1
->SetContentsOpaque(true);
5225 layer1
->SetExpectation(false, false);
5226 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5227 layer2
->SetExpectation(false, false);
5228 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5229 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5230 host_impl_
->DrawLayers(&frame
);
5231 EXPECT_TRUE(layer1
->quads_appended());
5232 EXPECT_TRUE(layer2
->quads_appended());
5233 host_impl_
->DidDrawAllLayers(frame
);
5235 // Parent layer with translucent opacity and opaque content. Since it has a
5236 // drawing child, it's drawn to a render surface which carries the opacity,
5237 // so it's itself drawn without blending.
5238 // Child layer with opaque content, drawn without blending (parent surface
5239 // carries the inherited opacity).
5240 layer1
->SetContentsOpaque(true);
5241 layer1
->SetOpacity(0.5f
);
5242 layer1
->SetHasRenderSurface(true);
5243 layer1
->SetExpectation(false, true);
5244 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5245 layer2
->SetExpectation(false, false);
5246 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5247 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
5248 host_impl_
->active_tree()->root_layer());
5249 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5250 host_impl_
->DrawLayers(&frame
);
5251 EXPECT_TRUE(layer1
->quads_appended());
5252 EXPECT_TRUE(layer2
->quads_appended());
5253 host_impl_
->DidDrawAllLayers(frame
);
5254 layer1
->SetHasRenderSurface(false);
5256 // Draw again, but with child non-opaque, to make sure
5257 // layer1 not culled.
5258 layer1
->SetContentsOpaque(true);
5259 layer1
->SetOpacity(1.f
);
5260 layer1
->SetExpectation(false, false);
5261 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5262 layer2
->SetContentsOpaque(true);
5263 layer2
->SetOpacity(0.5f
);
5264 layer2
->SetExpectation(true, false);
5265 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5266 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5267 host_impl_
->DrawLayers(&frame
);
5268 EXPECT_TRUE(layer1
->quads_appended());
5269 EXPECT_TRUE(layer2
->quads_appended());
5270 host_impl_
->DidDrawAllLayers(frame
);
5272 // A second way of making the child non-opaque.
5273 layer1
->SetContentsOpaque(true);
5274 layer1
->SetOpacity(1.f
);
5275 layer1
->SetExpectation(false, false);
5276 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5277 layer2
->SetContentsOpaque(false);
5278 layer2
->SetOpacity(1.f
);
5279 layer2
->SetExpectation(true, false);
5280 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5281 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5282 host_impl_
->DrawLayers(&frame
);
5283 EXPECT_TRUE(layer1
->quads_appended());
5284 EXPECT_TRUE(layer2
->quads_appended());
5285 host_impl_
->DidDrawAllLayers(frame
);
5287 // And when the layer says its not opaque but is painted opaque, it is not
5289 layer1
->SetContentsOpaque(true);
5290 layer1
->SetOpacity(1.f
);
5291 layer1
->SetExpectation(false, false);
5292 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5293 layer2
->SetContentsOpaque(true);
5294 layer2
->SetOpacity(1.f
);
5295 layer2
->SetExpectation(false, false);
5296 layer2
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5297 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5298 host_impl_
->DrawLayers(&frame
);
5299 EXPECT_TRUE(layer1
->quads_appended());
5300 EXPECT_TRUE(layer2
->quads_appended());
5301 host_impl_
->DidDrawAllLayers(frame
);
5303 // Layer with partially opaque contents, drawn with blending.
5304 layer1
->SetContentsOpaque(false);
5305 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5306 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
5307 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5308 layer1
->SetExpectation(true, false);
5309 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5310 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5311 host_impl_
->DrawLayers(&frame
);
5312 EXPECT_TRUE(layer1
->quads_appended());
5313 host_impl_
->DidDrawAllLayers(frame
);
5315 // Layer with partially opaque contents partially culled, drawn with blending.
5316 layer1
->SetContentsOpaque(false);
5317 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5318 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
5319 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5320 layer1
->SetExpectation(true, false);
5321 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5322 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5323 host_impl_
->DrawLayers(&frame
);
5324 EXPECT_TRUE(layer1
->quads_appended());
5325 host_impl_
->DidDrawAllLayers(frame
);
5327 // Layer with partially opaque contents culled, drawn with blending.
5328 layer1
->SetContentsOpaque(false);
5329 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5330 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
5331 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5332 layer1
->SetExpectation(true, false);
5333 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5334 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5335 host_impl_
->DrawLayers(&frame
);
5336 EXPECT_TRUE(layer1
->quads_appended());
5337 host_impl_
->DidDrawAllLayers(frame
);
5339 // Layer with partially opaque contents and translucent contents culled, drawn
5340 // without blending.
5341 layer1
->SetContentsOpaque(false);
5342 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
5343 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
5344 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
5345 layer1
->SetExpectation(false, false);
5346 layer1
->SetUpdateRect(gfx::Rect(layer1
->bounds()));
5347 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5348 host_impl_
->DrawLayers(&frame
);
5349 EXPECT_TRUE(layer1
->quads_appended());
5350 host_impl_
->DidDrawAllLayers(frame
);
5353 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
5355 LayerTreeHostImplViewportCoveredTest() :
5356 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
5358 did_activate_pending_tree_(false) {}
5360 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
5362 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
5364 return FakeOutputSurface::Create3d();
5367 void SetupActiveTreeLayers() {
5368 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
5369 host_impl_
->active_tree()->SetRootLayer(
5370 LayerImpl::Create(host_impl_
->active_tree(), 1));
5371 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
5372 host_impl_
->active_tree()->root_layer()->AddChild(
5373 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
5375 host_impl_
->resource_provider()));
5376 child_
= static_cast<BlendStateCheckLayer
*>(
5377 host_impl_
->active_tree()->root_layer()->children()[0]);
5378 child_
->SetExpectation(false, false);
5379 child_
->SetContentsOpaque(true);
5382 // Expect no gutter rects.
5383 void TestLayerCoversFullViewport() {
5384 gfx::Rect
layer_rect(viewport_size_
);
5385 child_
->SetPosition(layer_rect
.origin());
5386 child_
->SetBounds(layer_rect
.size());
5387 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5388 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5390 LayerTreeHostImpl::FrameData frame
;
5391 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5392 ASSERT_EQ(1u, frame
.render_passes
.size());
5394 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5395 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5396 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5398 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5399 host_impl_
->DidDrawAllLayers(frame
);
5402 // Expect fullscreen gutter rect.
5403 void TestEmptyLayer() {
5404 gfx::Rect
layer_rect(0, 0, 0, 0);
5405 child_
->SetPosition(layer_rect
.origin());
5406 child_
->SetBounds(layer_rect
.size());
5407 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5408 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5410 LayerTreeHostImpl::FrameData frame
;
5411 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5412 ASSERT_EQ(1u, frame
.render_passes
.size());
5414 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5415 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5416 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5418 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5419 host_impl_
->DidDrawAllLayers(frame
);
5422 // Expect four surrounding gutter rects.
5423 void TestLayerInMiddleOfViewport() {
5424 gfx::Rect
layer_rect(500, 500, 200, 200);
5425 child_
->SetPosition(layer_rect
.origin());
5426 child_
->SetBounds(layer_rect
.size());
5427 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5428 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5430 LayerTreeHostImpl::FrameData frame
;
5431 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5432 ASSERT_EQ(1u, frame
.render_passes
.size());
5434 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5435 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
5436 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5438 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
5439 host_impl_
->DidDrawAllLayers(frame
);
5442 // Expect no gutter rects.
5443 void TestLayerIsLargerThanViewport() {
5444 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
5445 viewport_size_
.height() + 10);
5446 child_
->SetPosition(layer_rect
.origin());
5447 child_
->SetBounds(layer_rect
.size());
5448 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
5449 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
5451 LayerTreeHostImpl::FrameData frame
;
5452 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5453 ASSERT_EQ(1u, frame
.render_passes
.size());
5455 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
5456 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
5457 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
5459 host_impl_
->DidDrawAllLayers(frame
);
5462 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
5464 void set_gutter_quad_material(DrawQuad::Material material
) {
5465 gutter_quad_material_
= material
;
5467 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
5468 gutter_texture_size_
= gutter_texture_size
;
5472 size_t CountGutterQuads(const QuadList
& quad_list
) {
5473 size_t num_gutter_quads
= 0;
5474 for (const auto& quad
: quad_list
) {
5475 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
5477 return num_gutter_quads
;
5480 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
5481 LayerTestCommon::VerifyQuadsExactlyCoverRect(
5482 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
5485 // Make sure that the texture coordinates match their expectations.
5486 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
5487 for (const auto& quad
: quad_list
) {
5488 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
5490 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
5491 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
5492 gutter_texture_size_
, host_impl_
->device_scale_factor());
5493 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
5494 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
5495 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
5496 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
5498 texture_quad
->uv_bottom_right
.x(),
5499 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
5501 texture_quad
->uv_bottom_right
.y(),
5502 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
5506 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
5507 return gfx::ToRoundedSize(
5508 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
5511 DrawQuad::Material gutter_quad_material_
;
5512 gfx::Size gutter_texture_size_
;
5513 gfx::Size viewport_size_
;
5514 BlendStateCheckLayer
* child_
;
5515 bool did_activate_pending_tree_
;
5518 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
5519 viewport_size_
= gfx::Size(1000, 1000);
5521 bool always_draw
= false;
5522 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5524 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5525 SetupActiveTreeLayers();
5526 TestLayerCoversFullViewport();
5528 TestLayerInMiddleOfViewport();
5529 TestLayerIsLargerThanViewport();
5532 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
5533 viewport_size_
= gfx::Size(1000, 1000);
5535 bool always_draw
= false;
5536 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5538 host_impl_
->SetDeviceScaleFactor(2.f
);
5539 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5540 SetupActiveTreeLayers();
5541 TestLayerCoversFullViewport();
5543 TestLayerInMiddleOfViewport();
5544 TestLayerIsLargerThanViewport();
5547 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
5548 viewport_size_
= gfx::Size(1000, 1000);
5550 bool always_draw
= true;
5551 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5553 // Pending tree to force active_tree size invalid. Not used otherwise.
5554 host_impl_
->CreatePendingTree();
5555 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5556 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5558 SetupActiveTreeLayers();
5560 TestLayerInMiddleOfViewport();
5561 TestLayerIsLargerThanViewport();
5564 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5565 viewport_size_
= gfx::Size(1000, 1000);
5567 bool always_draw
= true;
5568 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5570 // Set larger viewport and activate it to active tree.
5571 host_impl_
->CreatePendingTree();
5572 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5573 viewport_size_
.height() + 100);
5574 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5575 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5576 host_impl_
->ActivateSyncTree();
5577 EXPECT_TRUE(did_activate_pending_tree_
);
5578 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5580 // Shrink pending tree viewport without activating.
5581 host_impl_
->CreatePendingTree();
5582 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5583 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5585 SetupActiveTreeLayers();
5587 TestLayerInMiddleOfViewport();
5588 TestLayerIsLargerThanViewport();
5591 class FakeDrawableLayerImpl
: public LayerImpl
{
5593 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5594 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5597 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5598 : LayerImpl(tree_impl
, id
) {}
5601 // Only reshape when we know we are going to draw. Otherwise, the reshape
5602 // can leave the window at the wrong size if we never draw and the proper
5603 // viewport size is never set.
5604 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5605 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5606 scoped_ptr
<OutputSurface
> output_surface(
5607 FakeOutputSurface::Create3d(provider
));
5608 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5610 scoped_ptr
<LayerImpl
> root
=
5611 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5612 root
->SetBounds(gfx::Size(10, 10));
5613 root
->SetDrawsContent(true);
5614 root
->SetHasRenderSurface(true);
5615 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5616 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5617 provider
->TestContext3d()->clear_reshape_called();
5619 LayerTreeHostImpl::FrameData frame
;
5620 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5621 host_impl_
->SetDeviceScaleFactor(1.f
);
5622 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5623 host_impl_
->DrawLayers(&frame
);
5624 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5625 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5626 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5627 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5628 host_impl_
->DidDrawAllLayers(frame
);
5629 provider
->TestContext3d()->clear_reshape_called();
5631 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5632 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5633 host_impl_
->DrawLayers(&frame
);
5634 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5635 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5636 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5637 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5638 host_impl_
->DidDrawAllLayers(frame
);
5639 provider
->TestContext3d()->clear_reshape_called();
5641 host_impl_
->SetDeviceScaleFactor(2.f
);
5642 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5643 host_impl_
->DrawLayers(&frame
);
5644 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5645 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5646 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5647 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5648 host_impl_
->DidDrawAllLayers(frame
);
5649 provider
->TestContext3d()->clear_reshape_called();
5652 // Make sure damage tracking propagates all the way to the graphics context,
5653 // where it should request to swap only the sub-buffer that is damaged.
5654 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5655 scoped_refptr
<TestContextProvider
> context_provider(
5656 TestContextProvider::Create());
5657 context_provider
->BindToCurrentThread();
5658 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5660 scoped_ptr
<FakeOutputSurface
> output_surface(
5661 FakeOutputSurface::Create3d(context_provider
));
5662 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5664 // This test creates its own LayerTreeHostImpl, so
5665 // that we can force partial swap enabled.
5666 LayerTreeSettings settings
;
5667 settings
.renderer_settings
.partial_swap_enabled
= true;
5668 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5669 LayerTreeHostImpl::Create(
5670 settings
, this, &proxy_
, &stats_instrumentation_
,
5671 &shared_bitmap_manager_
, NULL
, &task_graph_runner_
, 0);
5672 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5673 layer_tree_host_impl
->WillBeginImplFrame(
5674 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5675 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5677 scoped_ptr
<LayerImpl
> root
=
5678 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5679 root
->SetHasRenderSurface(true);
5680 scoped_ptr
<LayerImpl
> child
=
5681 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5682 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5683 child
->SetBounds(gfx::Size(14, 15));
5684 child
->SetDrawsContent(true);
5685 root
->SetBounds(gfx::Size(500, 500));
5686 root
->SetDrawsContent(true);
5687 root
->AddChild(child
.Pass());
5688 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5690 LayerTreeHostImpl::FrameData frame
;
5692 // First frame, the entire screen should get swapped.
5693 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5694 layer_tree_host_impl
->DrawLayers(&frame
);
5695 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5696 layer_tree_host_impl
->SwapBuffers(frame
);
5697 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5698 EXPECT_EQ(expected_swap_rect
.ToString(),
5699 fake_output_surface
->last_swap_rect().ToString());
5701 // Second frame, only the damaged area should get swapped. Damage should be
5702 // the union of old and new child rects.
5703 // expected damage rect: gfx::Rect(26, 28);
5704 // expected swap rect: vertically flipped, with origin at bottom left corner.
5705 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5707 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5708 layer_tree_host_impl
->DrawLayers(&frame
);
5709 host_impl_
->DidDrawAllLayers(frame
);
5710 layer_tree_host_impl
->SwapBuffers(frame
);
5712 // Make sure that partial swap is constrained to the viewport dimensions
5713 // expected damage rect: gfx::Rect(500, 500);
5714 // expected swap rect: flipped damage rect, but also clamped to viewport
5715 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5716 EXPECT_EQ(expected_swap_rect
.ToString(),
5717 fake_output_surface
->last_swap_rect().ToString());
5719 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5720 // This will damage everything.
5721 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5723 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5724 layer_tree_host_impl
->DrawLayers(&frame
);
5725 host_impl_
->DidDrawAllLayers(frame
);
5726 layer_tree_host_impl
->SwapBuffers(frame
);
5728 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5729 EXPECT_EQ(expected_swap_rect
.ToString(),
5730 fake_output_surface
->last_swap_rect().ToString());
5733 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5734 scoped_ptr
<LayerImpl
> root
=
5735 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5736 scoped_ptr
<LayerImpl
> child
=
5737 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5738 child
->SetBounds(gfx::Size(10, 10));
5739 child
->SetDrawsContent(true);
5740 root
->SetBounds(gfx::Size(10, 10));
5741 root
->SetDrawsContent(true);
5742 root
->SetHasRenderSurface(true);
5743 root
->AddChild(child
.Pass());
5745 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5747 LayerTreeHostImpl::FrameData frame
;
5749 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5750 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5751 EXPECT_EQ(1u, frame
.render_passes
.size());
5752 host_impl_
->DidDrawAllLayers(frame
);
5755 class FakeLayerWithQuads
: public LayerImpl
{
5757 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5758 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5761 void AppendQuads(RenderPass
* render_pass
,
5762 AppendQuadsData
* append_quads_data
) override
{
5763 SharedQuadState
* shared_quad_state
=
5764 render_pass
->CreateAndAppendSharedQuadState();
5765 PopulateSharedQuadState(shared_quad_state
);
5767 SkColor gray
= SkColorSetRGB(100, 100, 100);
5768 gfx::Rect
quad_rect(bounds());
5769 gfx::Rect
visible_quad_rect(quad_rect
);
5770 SolidColorDrawQuad
* my_quad
=
5771 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5773 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5777 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5778 : LayerImpl(tree_impl
, id
) {}
5781 class MockContext
: public TestWebGraphicsContext3D
{
5783 MOCK_METHOD1(useProgram
, void(GLuint program
));
5784 MOCK_METHOD5(uniform4f
, void(GLint location
,
5789 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5791 GLboolean transpose
,
5792 const GLfloat
* value
));
5793 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5797 MOCK_METHOD1(enable
, void(GLenum cap
));
5798 MOCK_METHOD1(disable
, void(GLenum cap
));
5799 MOCK_METHOD4(scissor
, void(GLint x
,
5805 class MockContextHarness
{
5807 MockContext
* context_
;
5810 explicit MockContextHarness(MockContext
* context
)
5811 : context_(context
) {
5812 context_
->set_have_post_sub_buffer(true);
5814 // Catch "uninteresting" calls
5815 EXPECT_CALL(*context_
, useProgram(_
))
5818 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5821 // These are not asserted
5822 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5823 .WillRepeatedly(Return());
5825 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5826 .WillRepeatedly(Return());
5828 // Any un-sanctioned calls to enable() are OK
5829 EXPECT_CALL(*context_
, enable(_
))
5830 .WillRepeatedly(Return());
5832 // Any un-sanctioned calls to disable() are OK
5833 EXPECT_CALL(*context_
, disable(_
))
5834 .WillRepeatedly(Return());
5837 void MustDrawSolidQuad() {
5838 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5840 .RetiresOnSaturation();
5842 EXPECT_CALL(*context_
, useProgram(_
))
5844 .RetiresOnSaturation();
5847 void MustSetScissor(int x
, int y
, int width
, int height
) {
5848 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5849 .WillRepeatedly(Return());
5851 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5853 .WillRepeatedly(Return());
5856 void MustSetNoScissor() {
5857 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5858 .WillRepeatedly(Return());
5860 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5863 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5868 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5869 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5870 MockContext
* mock_context
= mock_context_owned
.get();
5871 MockContextHarness
harness(mock_context
);
5874 LayerTreeSettings settings
= DefaultSettings();
5875 settings
.renderer_settings
.partial_swap_enabled
= false;
5876 CreateHostImpl(settings
,
5877 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5878 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5880 // Without partial swap, and no clipping, no scissor is set.
5881 harness
.MustDrawSolidQuad();
5882 harness
.MustSetNoScissor();
5884 LayerTreeHostImpl::FrameData frame
;
5885 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5886 host_impl_
->DrawLayers(&frame
);
5887 host_impl_
->DidDrawAllLayers(frame
);
5889 Mock::VerifyAndClearExpectations(&mock_context
);
5891 // Without partial swap, but a layer does clip its subtree, one scissor is
5893 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5894 harness
.MustDrawSolidQuad();
5895 harness
.MustSetScissor(0, 0, 10, 10);
5897 LayerTreeHostImpl::FrameData frame
;
5898 host_impl_
->active_tree()->BuildPropertyTreesForTesting();
5899 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5900 host_impl_
->DrawLayers(&frame
);
5901 host_impl_
->DidDrawAllLayers(frame
);
5903 Mock::VerifyAndClearExpectations(&mock_context
);
5906 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5907 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5908 MockContext
* mock_context
= context_owned
.get();
5909 MockContextHarness
harness(mock_context
);
5911 LayerTreeSettings settings
= DefaultSettings();
5912 settings
.renderer_settings
.partial_swap_enabled
= true;
5913 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5914 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5916 // The first frame is not a partially-swapped one. No scissor should be set.
5917 harness
.MustSetNoScissor();
5918 harness
.MustDrawSolidQuad();
5920 LayerTreeHostImpl::FrameData frame
;
5921 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5922 host_impl_
->DrawLayers(&frame
);
5923 host_impl_
->DidDrawAllLayers(frame
);
5925 Mock::VerifyAndClearExpectations(&mock_context
);
5927 // Damage a portion of the frame.
5928 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5929 gfx::Rect(0, 0, 2, 3));
5931 // The second frame will be partially-swapped (the y coordinates are flipped).
5932 harness
.MustSetScissor(0, 7, 2, 3);
5933 harness
.MustDrawSolidQuad();
5935 LayerTreeHostImpl::FrameData frame
;
5936 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5937 host_impl_
->DrawLayers(&frame
);
5938 host_impl_
->DidDrawAllLayers(frame
);
5940 Mock::VerifyAndClearExpectations(&mock_context
);
5943 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5945 LayerTreeHostImplClient
* client
,
5947 SharedBitmapManager
* manager
,
5948 TaskGraphRunner
* task_graph_runner
,
5949 RenderingStatsInstrumentation
* stats_instrumentation
) {
5950 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5951 scoped_ptr
<OutputSurface
> output_surface(
5952 FakeOutputSurface::Create3d(provider
));
5953 provider
->BindToCurrentThread();
5954 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5956 LayerTreeSettings settings
;
5957 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5958 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5959 LayerTreeHostImpl::Create(settings
, client
, proxy
, stats_instrumentation
,
5960 manager
, nullptr, task_graph_runner
, 0);
5961 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5962 my_host_impl
->WillBeginImplFrame(
5963 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5964 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5967 Layers are created as follows:
5969 +--------------------+
5973 | | +-------------------+
5975 | | +-------------------+
5980 +--------------------+
5982 Layers 1, 2 have render surfaces
5984 scoped_ptr
<LayerImpl
> root
=
5985 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5986 scoped_ptr
<LayerImpl
> child
=
5987 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5988 scoped_ptr
<LayerImpl
> grand_child
=
5989 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5991 gfx::Rect
root_rect(0, 0, 100, 100);
5992 gfx::Rect
child_rect(10, 10, 50, 50);
5993 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5995 root
->SetHasRenderSurface(true);
5996 root
->SetPosition(root_rect
.origin());
5997 root
->SetBounds(root_rect
.size());
5998 root
->draw_properties().visible_layer_rect
= root_rect
;
5999 root
->SetDrawsContent(false);
6000 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
6002 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
6003 child
->SetOpacity(0.5f
);
6004 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
6005 child
->draw_properties().visible_layer_rect
= child_rect
;
6006 child
->SetDrawsContent(false);
6007 child
->SetHasRenderSurface(true);
6009 grand_child
->SetPosition(grand_child_rect
.origin());
6010 grand_child
->SetBounds(grand_child_rect
.size());
6011 grand_child
->draw_properties().visible_layer_rect
= grand_child_rect
;
6012 grand_child
->SetDrawsContent(true);
6014 child
->AddChild(grand_child
.Pass());
6015 root
->AddChild(child
.Pass());
6017 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
6018 return my_host_impl
.Pass();
6021 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
6022 TestSharedBitmapManager shared_bitmap_manager
;
6023 TestTaskGraphRunner task_graph_runner
;
6024 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
6025 SetupLayersForOpacity(true, this, &proxy_
, &shared_bitmap_manager
,
6026 &task_graph_runner
, &stats_instrumentation_
);
6028 LayerTreeHostImpl::FrameData frame
;
6029 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
6031 // Verify all quads have been computed
6032 ASSERT_EQ(2U, frame
.render_passes
.size());
6033 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
6034 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
6035 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
6036 frame
.render_passes
[0]->quad_list
.front()->material
);
6037 EXPECT_EQ(DrawQuad::RENDER_PASS
,
6038 frame
.render_passes
[1]->quad_list
.front()->material
);
6040 my_host_impl
->DrawLayers(&frame
);
6041 my_host_impl
->DidDrawAllLayers(frame
);
6045 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
6046 TestSharedBitmapManager shared_bitmap_manager
;
6047 TestTaskGraphRunner task_graph_runner
;
6048 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
6049 SetupLayersForOpacity(false, this, &proxy_
, &shared_bitmap_manager
,
6050 &task_graph_runner
, &stats_instrumentation_
);
6052 LayerTreeHostImpl::FrameData frame
;
6053 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
6055 // Verify all quads have been computed
6056 ASSERT_EQ(2U, frame
.render_passes
.size());
6057 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
6058 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
6059 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
6060 frame
.render_passes
[0]->quad_list
.front()->material
);
6061 EXPECT_EQ(DrawQuad::RENDER_PASS
,
6062 frame
.render_passes
[1]->quad_list
.front()->material
);
6064 my_host_impl
->DrawLayers(&frame
);
6065 my_host_impl
->DidDrawAllLayers(frame
);
6069 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
6070 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6071 TestWebGraphicsContext3D::Create();
6072 TestWebGraphicsContext3D
* context3d
= context
.get();
6073 scoped_ptr
<OutputSurface
> output_surface(
6074 FakeOutputSurface::Create3d(context
.Pass()));
6075 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6077 scoped_ptr
<LayerImpl
> root_layer
=
6078 LayerImpl::Create(host_impl_
->active_tree(), 1);
6079 root_layer
->SetBounds(gfx::Size(10, 10));
6080 root_layer
->SetHasRenderSurface(true);
6082 scoped_refptr
<VideoFrame
> softwareFrame
=
6083 media::VideoFrame::CreateColorFrame(
6084 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
6085 FakeVideoFrameProvider provider
;
6086 provider
.set_frame(softwareFrame
);
6087 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6088 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
6089 video_layer
->SetBounds(gfx::Size(10, 10));
6090 video_layer
->SetDrawsContent(true);
6091 root_layer
->AddChild(video_layer
.Pass());
6093 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
6094 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
6095 io_surface_layer
->SetBounds(gfx::Size(10, 10));
6096 io_surface_layer
->SetDrawsContent(true);
6097 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
6098 root_layer
->AddChild(io_surface_layer
.Pass());
6100 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
6102 EXPECT_EQ(0u, context3d
->NumTextures());
6104 LayerTreeHostImpl::FrameData frame
;
6105 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6106 host_impl_
->DrawLayers(&frame
);
6107 host_impl_
->DidDrawAllLayers(frame
);
6108 host_impl_
->SwapBuffers(frame
);
6110 EXPECT_GT(context3d
->NumTextures(), 0u);
6112 // Kill the layer tree.
6113 host_impl_
->active_tree()->SetRootLayer(
6114 LayerImpl::Create(host_impl_
->active_tree(), 100));
6115 // There should be no textures left in use after.
6116 EXPECT_EQ(0u, context3d
->NumTextures());
6119 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
6121 MOCK_METHOD1(useProgram
, void(GLuint program
));
6122 MOCK_METHOD4(drawElements
, void(GLenum mode
,
6128 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
6129 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
6130 new MockDrawQuadsToFillScreenContext
);
6131 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
6134 LayerTreeSettings settings
= DefaultSettings();
6135 settings
.renderer_settings
.partial_swap_enabled
= false;
6136 CreateHostImpl(settings
,
6137 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
6138 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6139 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
6141 // Verify one quad is drawn when transparent background set is not set.
6142 host_impl_
->active_tree()->set_has_transparent_background(false);
6143 EXPECT_CALL(*mock_context
, useProgram(_
))
6145 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
6147 LayerTreeHostImpl::FrameData frame
;
6148 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6149 host_impl_
->DrawLayers(&frame
);
6150 host_impl_
->DidDrawAllLayers(frame
);
6151 Mock::VerifyAndClearExpectations(&mock_context
);
6153 // Verify no quads are drawn when transparent background is set.
6154 host_impl_
->active_tree()->set_has_transparent_background(true);
6155 host_impl_
->SetFullRootLayerDamage();
6156 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6157 host_impl_
->DrawLayers(&frame
);
6158 host_impl_
->DidDrawAllLayers(frame
);
6159 Mock::VerifyAndClearExpectations(&mock_context
);
6162 class LayerTreeHostImplTestWithDelegatingRenderer
6163 : public LayerTreeHostImplTest
{
6165 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
6166 return FakeOutputSurface::CreateDelegating3d();
6169 void DrawFrameAndTestDamage(const gfx::Rect
& expected_damage
) {
6170 bool expect_to_draw
= !expected_damage
.IsEmpty();
6172 LayerTreeHostImpl::FrameData frame
;
6173 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6175 if (!expect_to_draw
) {
6176 // With no damage, we don't draw, and no quads are created.
6177 ASSERT_EQ(0u, frame
.render_passes
.size());
6179 ASSERT_EQ(1u, frame
.render_passes
.size());
6181 // Verify the damage rect for the root render pass.
6182 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
6183 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
6185 // Verify the root and child layers' quads are generated and not being
6187 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
6189 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
6190 gfx::Rect
expected_child_visible_rect(child
->bounds());
6191 EXPECT_EQ(expected_child_visible_rect
,
6192 root_render_pass
->quad_list
.front()->visible_rect
);
6194 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
6195 gfx::Rect
expected_root_visible_rect(root
->bounds());
6196 EXPECT_EQ(expected_root_visible_rect
,
6197 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
6200 host_impl_
->DrawLayers(&frame
);
6201 host_impl_
->DidDrawAllLayers(frame
);
6202 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
6206 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
6207 scoped_ptr
<SolidColorLayerImpl
> root
=
6208 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6209 root
->SetPosition(gfx::PointF());
6210 root
->SetBounds(gfx::Size(10, 10));
6211 root
->SetDrawsContent(true);
6212 root
->SetHasRenderSurface(true);
6214 // Child layer is in the bottom right corner.
6215 scoped_ptr
<SolidColorLayerImpl
> child
=
6216 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
6217 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
6218 child
->SetBounds(gfx::Size(1, 1));
6219 child
->SetDrawsContent(true);
6220 root
->AddChild(child
.Pass());
6222 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6224 // Draw a frame. In the first frame, the entire viewport should be damaged.
6225 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6226 DrawFrameAndTestDamage(full_frame_damage
);
6228 // The second frame has damage that doesn't touch the child layer. Its quads
6229 // should still be generated.
6230 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
6231 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
6232 DrawFrameAndTestDamage(small_damage
);
6234 // The third frame should have no damage, so no quads should be generated.
6235 gfx::Rect no_damage
;
6236 DrawFrameAndTestDamage(no_damage
);
6239 // TODO(reveman): Remove this test and the ability to prevent on demand raster
6240 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
6241 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
6242 LayerTreeSettings settings
;
6243 CreateHostImpl(settings
, CreateOutputSurface());
6244 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
6247 class FakeMaskLayerImpl
: public LayerImpl
{
6249 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
6251 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
6254 void GetContentsResourceId(ResourceId
* resource_id
,
6255 gfx::Size
* resource_size
) const override
{
6260 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
6261 : LayerImpl(tree_impl
, id
) {}
6264 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
6266 using GLRenderer::ShouldAntialiasQuad
;
6269 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
6270 // Due to precision issues (especially on Android), sometimes far
6271 // away quads can end up thinking they need AA.
6272 float device_scale_factor
= 4.f
/ 3.f
;
6273 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
6274 gfx::Size
root_size(2000, 1000);
6275 gfx::Size device_viewport_size
=
6276 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
6277 host_impl_
->SetViewportSize(device_viewport_size
);
6279 host_impl_
->CreatePendingTree();
6280 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
6283 scoped_ptr
<LayerImpl
> scoped_root
=
6284 LayerImpl::Create(host_impl_
->pending_tree(), 1);
6285 LayerImpl
* root
= scoped_root
.get();
6286 root
->SetHasRenderSurface(true);
6288 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
6290 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
6291 LayerImpl::Create(host_impl_
->pending_tree(), 2);
6292 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
6293 root
->AddChild(scoped_scrolling_layer
.Pass());
6295 gfx::Size
content_layer_bounds(100000, 100);
6296 gfx::Size
pile_tile_size(3000, 3000);
6297 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
6298 pile_tile_size
, content_layer_bounds
));
6300 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
6301 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
6303 LayerImpl
* content_layer
= scoped_content_layer
.get();
6304 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
6305 content_layer
->SetBounds(content_layer_bounds
);
6306 content_layer
->SetDrawsContent(true);
6308 root
->SetBounds(root_size
);
6310 gfx::ScrollOffset
scroll_offset(100000, 0);
6311 scrolling_layer
->SetScrollClipLayer(root
->id());
6312 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
6314 host_impl_
->ActivateSyncTree();
6316 bool update_lcd_text
= false;
6317 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
6318 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
6320 LayerTreeHostImpl::FrameData frame
;
6321 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6323 ASSERT_EQ(1u, frame
.render_passes
.size());
6324 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
6325 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
6327 bool clipped
= false, force_aa
= false;
6328 gfx::QuadF device_layer_quad
= MathUtil::MapQuad(
6329 quad
->shared_quad_state
->quad_to_target_transform
,
6330 gfx::QuadF(gfx::RectF(quad
->shared_quad_state
->visible_quad_layer_rect
)),
6332 EXPECT_FALSE(clipped
);
6334 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
6335 device_layer_quad
, clipped
, force_aa
);
6336 EXPECT_FALSE(antialiased
);
6338 host_impl_
->DrawLayers(&frame
);
6339 host_impl_
->DidDrawAllLayers(frame
);
6343 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
6345 CompositorFrameMetadataTest()
6346 : swap_buffers_complete_(0) {}
6348 void DidSwapBuffersCompleteOnImplThread() override
{
6349 swap_buffers_complete_
++;
6352 int swap_buffers_complete_
;
6355 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
6356 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
6358 LayerTreeHostImpl::FrameData frame
;
6359 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6360 host_impl_
->DrawLayers(&frame
);
6361 host_impl_
->DidDrawAllLayers(frame
);
6363 CompositorFrameAck ack
;
6364 host_impl_
->ReclaimResources(&ack
);
6365 host_impl_
->DidSwapBuffersComplete();
6366 EXPECT_EQ(swap_buffers_complete_
, 1);
6369 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
6371 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
6373 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
6375 return SoftwareOutputDevice::BeginPaint(damage_rect
);
6377 void EndPaint() override
{
6378 SoftwareOutputDevice::EndPaint();
6382 int frames_began_
, frames_ended_
;
6385 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
6386 // No main thread evictions in resourceless software mode.
6387 set_reduce_memory_result(false);
6388 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
6389 EXPECT_TRUE(CreateHostImpl(
6391 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
6392 host_impl_
->SetViewportSize(gfx::Size(50, 50));
6394 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6396 const gfx::Transform external_transform
;
6397 const gfx::Rect external_viewport
;
6398 const gfx::Rect external_clip
;
6399 const bool resourceless_software_draw
= true;
6400 host_impl_
->SetExternalDrawConstraints(external_transform
,
6405 resourceless_software_draw
);
6407 EXPECT_EQ(0, software_device
->frames_began_
);
6408 EXPECT_EQ(0, software_device
->frames_ended_
);
6412 EXPECT_EQ(1, software_device
->frames_began_
);
6413 EXPECT_EQ(1, software_device
->frames_ended_
);
6415 // Call another API method that is likely to hit nullptr in this mode.
6416 scoped_refptr
<base::trace_event::TracedValue
> state
=
6417 make_scoped_refptr(new base::trace_event::TracedValue());
6418 host_impl_
->ActivationStateAsValueInto(state
.get());
6421 TEST_F(LayerTreeHostImplTest
,
6422 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
6423 set_reduce_memory_result(false);
6424 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
6425 FakeOutputSurface::CreateSoftware(
6426 make_scoped_ptr(new CountingSoftwareDevice
))));
6428 const gfx::Transform external_transform
;
6429 const gfx::Rect external_viewport
;
6430 const gfx::Rect external_clip
;
6431 const bool resourceless_software_draw
= true;
6432 host_impl_
->SetExternalDrawConstraints(external_transform
,
6437 resourceless_software_draw
);
6439 // SolidColorLayerImpl will be drawn.
6440 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
6441 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6443 // VideoLayerImpl will not be drawn.
6444 FakeVideoFrameProvider provider
;
6445 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
6446 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
6447 video_layer
->SetBounds(gfx::Size(10, 10));
6448 video_layer
->SetDrawsContent(true);
6449 root_layer
->AddChild(video_layer
.Pass());
6450 SetupRootLayerImpl(root_layer
.Pass());
6452 LayerTreeHostImpl::FrameData frame
;
6453 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6454 host_impl_
->DrawLayers(&frame
);
6455 host_impl_
->DidDrawAllLayers(frame
);
6457 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
6458 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
6461 // Checks that we have a non-0 default allocation if we pass a context that
6462 // doesn't support memory management extensions.
6463 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
6464 LayerTreeSettings settings
;
6465 host_impl_
= LayerTreeHostImpl::Create(
6466 settings
, this, &proxy_
, &stats_instrumentation_
, &shared_bitmap_manager_
,
6467 &gpu_memory_buffer_manager_
, &task_graph_runner_
, 0);
6469 scoped_ptr
<OutputSurface
> output_surface(
6470 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
6471 host_impl_
->InitializeRenderer(output_surface
.Pass());
6472 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
6475 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6476 ASSERT_TRUE(host_impl_
->active_tree());
6478 // RequiresHighResToDraw is set when new output surface is used.
6479 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6481 host_impl_
->ResetRequiresHighResToDraw();
6483 host_impl_
->SetVisible(false);
6484 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6485 host_impl_
->SetVisible(true);
6486 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6487 host_impl_
->SetVisible(false);
6488 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6490 host_impl_
->ResetRequiresHighResToDraw();
6492 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6493 host_impl_
->SetVisible(true);
6494 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6497 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6498 ASSERT_TRUE(host_impl_
->active_tree());
6499 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6501 // RequiresHighResToDraw is set when new output surface is used.
6502 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6504 host_impl_
->ResetRequiresHighResToDraw();
6506 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6507 host_impl_
->SetHasGpuRasterizationTrigger(false);
6508 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6509 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6510 host_impl_
->SetHasGpuRasterizationTrigger(true);
6511 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6512 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6513 host_impl_
->SetHasGpuRasterizationTrigger(false);
6514 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6515 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6517 host_impl_
->ResetRequiresHighResToDraw();
6519 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6520 host_impl_
->SetHasGpuRasterizationTrigger(true);
6521 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6522 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6525 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6527 void SetUp() override
{
6529 new FakeLayerTreeHostImpl(LayerTreeSettings(), &proxy_
,
6530 &shared_bitmap_manager_
, &task_graph_runner_
);
6531 host_impl_
.reset(fake_host_impl_
);
6532 host_impl_
->InitializeRenderer(CreateOutputSurface());
6533 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6536 FakeLayerTreeHostImpl
* fake_host_impl_
;
6539 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6540 fake_host_impl_
->DidModifyTilePriorities();
6541 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6542 fake_host_impl_
->SetVisible(false);
6543 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6546 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6547 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6548 TestWebGraphicsContext3D::Create();
6549 TestWebGraphicsContext3D
* context3d
= context
.get();
6550 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6551 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6553 EXPECT_EQ(0u, context3d
->NumTextures());
6555 UIResourceId ui_resource_id
= 1;
6556 bool is_opaque
= false;
6557 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6558 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6559 EXPECT_EQ(1u, context3d
->NumTextures());
6560 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6563 // Multiple requests with the same id is allowed. The previous texture is
6565 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6566 EXPECT_EQ(1u, context3d
->NumTextures());
6567 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6569 EXPECT_NE(id1
, id2
);
6571 // Deleting invalid UIResourceId is allowed and does not change state.
6572 host_impl_
->DeleteUIResource(-1);
6573 EXPECT_EQ(1u, context3d
->NumTextures());
6575 // Should return zero for invalid UIResourceId. Number of textures should
6577 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6578 EXPECT_EQ(1u, context3d
->NumTextures());
6580 host_impl_
->DeleteUIResource(ui_resource_id
);
6581 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6582 EXPECT_EQ(0u, context3d
->NumTextures());
6584 // Should not change state for multiple deletion on one UIResourceId
6585 host_impl_
->DeleteUIResource(ui_resource_id
);
6586 EXPECT_EQ(0u, context3d
->NumTextures());
6589 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6590 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6591 TestWebGraphicsContext3D::Create();
6592 TestWebGraphicsContext3D
* context3d
= context
.get();
6593 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6595 EXPECT_EQ(0u, context3d
->NumTextures());
6597 gfx::Size
size(4, 4);
6598 // SkImageInfo has no support for ETC1. The |info| below contains the right
6599 // total pixel size for the bitmap but not the right height and width. The
6600 // correct width/height are passed directly to UIResourceBitmap.
6602 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6603 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6604 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6605 pixel_ref
->setImmutable();
6606 UIResourceBitmap
bitmap(pixel_ref
, size
);
6607 UIResourceId ui_resource_id
= 1;
6608 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6609 EXPECT_EQ(1u, context3d
->NumTextures());
6610 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6614 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6617 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6618 scoped_refptr
<TestContextProvider
> context_provider
=
6619 TestContextProvider::Create();
6621 CreateHostImpl(DefaultSettings(),
6622 FakeOutputSurface::Create3d(context_provider
));
6624 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6626 ScopedPtrVector
<CopyOutputRequest
> requests
;
6627 requests
.push_back(CopyOutputRequest::CreateRequest(
6628 base::Bind(&ShutdownReleasesContext_Callback
)));
6630 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6632 LayerTreeHostImpl::FrameData frame
;
6633 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6634 host_impl_
->DrawLayers(&frame
);
6635 host_impl_
->DidDrawAllLayers(frame
);
6637 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6638 // texture in a texture mailbox.
6639 EXPECT_FALSE(context_provider
->HasOneRef());
6640 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6642 host_impl_
= nullptr;
6644 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6645 // released, and the texture deleted.
6646 EXPECT_TRUE(context_provider
->HasOneRef());
6647 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6650 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6651 // When flinging via touch, only the child should scroll (we should not
6653 gfx::Size
surface_size(10, 10);
6654 gfx::Size
content_size(20, 20);
6655 scoped_ptr
<LayerImpl
> root_clip
=
6656 LayerImpl::Create(host_impl_
->active_tree(), 3);
6657 root_clip
->SetHasRenderSurface(true);
6659 scoped_ptr
<LayerImpl
> root
=
6660 CreateScrollableLayer(1, content_size
, root_clip
.get());
6661 root
->SetIsContainerForFixedPositionLayers(true);
6662 scoped_ptr
<LayerImpl
> child
=
6663 CreateScrollableLayer(2, content_size
, root_clip
.get());
6665 root
->AddChild(child
.Pass());
6666 int root_id
= root
->id();
6667 root_clip
->AddChild(root
.Pass());
6669 host_impl_
->SetViewportSize(surface_size
);
6670 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6671 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6673 host_impl_
->active_tree()->DidBecomeActive();
6676 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6677 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6679 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6681 gfx::Vector2d
scroll_delta(0, 100);
6682 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6683 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6685 host_impl_
->ScrollEnd();
6687 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6688 host_impl_
->ProcessScrollDeltas();
6690 // Only the child should have scrolled.
6691 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6692 ExpectNone(*scroll_info
.get(), root_id
);
6696 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6697 // Scroll a child layer beyond its maximum scroll range and make sure the
6698 // the scroll doesn't bubble up to the parent layer.
6699 gfx::Size
surface_size(10, 10);
6700 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6701 root
->SetHasRenderSurface(true);
6702 scoped_ptr
<LayerImpl
> root_scrolling
=
6703 CreateScrollableLayer(2, surface_size
, root
.get());
6705 scoped_ptr
<LayerImpl
> grand_child
=
6706 CreateScrollableLayer(4, surface_size
, root
.get());
6707 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6709 scoped_ptr
<LayerImpl
> child
=
6710 CreateScrollableLayer(3, surface_size
, root
.get());
6711 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6712 child
->AddChild(grand_child
.Pass());
6714 root_scrolling
->AddChild(child
.Pass());
6715 root
->AddChild(root_scrolling
.Pass());
6716 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6717 host_impl_
->active_tree()->DidBecomeActive();
6718 host_impl_
->SetViewportSize(surface_size
);
6721 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6723 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6724 LayerImpl
* grand_child
= child
->children()[0];
6726 gfx::Vector2d
scroll_delta(0, -2);
6727 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6728 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6729 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6731 // The grand child should have scrolled up to its limit.
6732 scroll_info
= host_impl_
->ProcessScrollDeltas();
6733 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6735 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6736 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6738 // The child should have received the bubbled delta, but the locked
6739 // scrolling layer should remain set as the grand child.
6740 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6741 scroll_info
= host_impl_
->ProcessScrollDeltas();
6742 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6744 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6745 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(), scroll_delta
));
6746 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6748 // The first |ScrollBy| after the fling should re-lock the scrolling
6749 // layer to the first layer that scrolled, which is the child.
6750 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6751 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6752 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6754 // The child should have scrolled up to its limit.
6755 scroll_info
= host_impl_
->ProcessScrollDeltas();
6756 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6758 ScrollInfoContains(*scroll_info
, grand_child
->id(), scroll_delta
));
6759 EXPECT_TRUE(ScrollInfoContains(*scroll_info
, child
->id(),
6760 scroll_delta
+ scroll_delta
));
6762 // As the locked layer is at it's limit, no further scrolling can occur.
6763 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6764 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6765 host_impl_
->ScrollEnd();
6769 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6770 // When flinging via wheel, the root should eventually scroll (we should
6772 gfx::Size
surface_size(10, 10);
6773 gfx::Size
content_size(20, 20);
6774 scoped_ptr
<LayerImpl
> root_clip
=
6775 LayerImpl::Create(host_impl_
->active_tree(), 3);
6776 root_clip
->SetHasRenderSurface(true);
6777 scoped_ptr
<LayerImpl
> root_scroll
=
6778 CreateScrollableLayer(1, content_size
, root_clip
.get());
6779 int root_scroll_id
= root_scroll
->id();
6780 scoped_ptr
<LayerImpl
> child
=
6781 CreateScrollableLayer(2, content_size
, root_clip
.get());
6783 root_scroll
->AddChild(child
.Pass());
6784 root_clip
->AddChild(root_scroll
.Pass());
6786 host_impl_
->SetViewportSize(surface_size
);
6787 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6788 host_impl_
->active_tree()->DidBecomeActive();
6791 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6792 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6794 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6796 gfx::Vector2d
scroll_delta(0, 100);
6797 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6798 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6800 host_impl_
->ScrollEnd();
6802 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6803 host_impl_
->ProcessScrollDeltas();
6805 // The root should have scrolled.
6806 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6807 EXPECT_TRUE(ScrollInfoContains(*scroll_info
.get(), root_scroll_id
,
6808 gfx::Vector2d(0, 10)));
6812 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6813 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6814 // we should return SCROLL_UNKNOWN.
6815 gfx::Size
content_size(100, 100);
6816 SetupScrollAndContentsLayers(content_size
);
6818 int scroll_layer_id
= 2;
6819 LayerImpl
* scroll_layer
=
6820 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6821 scroll_layer
->SetDrawsContent(true);
6823 int page_scale_layer_id
= 5;
6824 LayerImpl
* page_scale_layer
=
6825 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6827 int occluder_layer_id
= 6;
6828 scoped_ptr
<LayerImpl
> occluder_layer
=
6829 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6830 occluder_layer
->SetDrawsContent(true);
6831 occluder_layer
->SetBounds(content_size
);
6832 occluder_layer
->SetPosition(gfx::PointF());
6834 // The parent of the occluder is *above* the scroller.
6835 page_scale_layer
->AddChild(occluder_layer
.Pass());
6839 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6840 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6843 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6844 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6845 // is not the first scroller we encounter when walking up from the layer, we
6846 // should also return SCROLL_UNKNOWN.
6847 gfx::Size
content_size(100, 100);
6848 SetupScrollAndContentsLayers(content_size
);
6850 int scroll_layer_id
= 2;
6851 LayerImpl
* scroll_layer
=
6852 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6853 scroll_layer
->SetDrawsContent(true);
6855 int occluder_layer_id
= 6;
6856 scoped_ptr
<LayerImpl
> occluder_layer
=
6857 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6858 occluder_layer
->SetDrawsContent(true);
6859 occluder_layer
->SetBounds(content_size
);
6860 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6862 int child_scroll_clip_layer_id
= 7;
6863 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6864 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6866 int child_scroll_layer_id
= 8;
6867 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6868 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6870 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6872 child_scroll
->AddChild(occluder_layer
.Pass());
6873 scroll_layer
->AddChild(child_scroll
.Pass());
6877 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6878 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6881 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6882 gfx::Size
content_size(100, 100);
6883 SetupScrollAndContentsLayers(content_size
);
6885 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6887 int scroll_layer_id
= 2;
6888 LayerImpl
* scroll_layer
=
6889 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6891 int child_scroll_layer_id
= 7;
6892 scoped_ptr
<LayerImpl
> child_scroll
=
6893 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6894 child_scroll
->SetDrawsContent(false);
6896 scroll_layer
->AddChild(child_scroll
.Pass());
6900 // We should not have scrolled |child_scroll| even though we technically "hit"
6901 // it. The reason for this is that if the scrolling the scroll would not move
6902 // any layer that is a drawn RSLL member, then we can ignore the hit.
6904 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6905 // started scrolling the inner viewport.
6906 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6907 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6909 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6912 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6913 gfx::Size
content_size(100, 100);
6914 SetupScrollAndContentsLayers(content_size
);
6916 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6917 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6919 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6920 CreateScrollableLayer(7, content_size
, root
);
6921 invisible_scroll_layer
->SetDrawsContent(false);
6923 scoped_ptr
<LayerImpl
> child_layer
=
6924 LayerImpl::Create(host_impl_
->active_tree(), 8);
6925 child_layer
->SetDrawsContent(false);
6927 scoped_ptr
<LayerImpl
> grand_child_layer
=
6928 LayerImpl::Create(host_impl_
->active_tree(), 9);
6929 grand_child_layer
->SetDrawsContent(true);
6930 grand_child_layer
->SetBounds(content_size
);
6931 // Move the grand child so it's not hit by our test point.
6932 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6934 child_layer
->AddChild(grand_child_layer
.Pass());
6935 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6936 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6940 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6941 // a descendant which is a drawn RSLL member.
6942 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6943 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6945 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6948 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6949 // This test case is very similar to the one above with one key difference:
6950 // the invisible scroller has a scroll child that is indeed draw contents.
6951 // If we attempt to initiate a gesture scroll off of the visible scroll child
6952 // we should still start the scroll child.
6953 gfx::Size
content_size(100, 100);
6954 SetupScrollAndContentsLayers(content_size
);
6956 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6958 int scroll_layer_id
= 2;
6959 LayerImpl
* scroll_layer
=
6960 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6962 int scroll_child_id
= 6;
6963 scoped_ptr
<LayerImpl
> scroll_child
=
6964 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6965 scroll_child
->SetDrawsContent(true);
6966 scroll_child
->SetBounds(content_size
);
6967 // Move the scroll child so it's not hit by our test point.
6968 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6970 int invisible_scroll_layer_id
= 7;
6971 scoped_ptr
<LayerImpl
> invisible_scroll
=
6972 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6973 invisible_scroll
->SetDrawsContent(false);
6975 int container_id
= 8;
6976 scoped_ptr
<LayerImpl
> container
=
6977 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6979 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6980 scroll_children
->insert(scroll_child
.get());
6981 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6983 scroll_child
->SetScrollParent(invisible_scroll
.get());
6985 container
->AddChild(invisible_scroll
.Pass());
6986 container
->AddChild(scroll_child
.Pass());
6988 scroll_layer
->AddChild(container
.Pass());
6992 // We should have scrolled |child_scroll| even though it is invisible.
6993 // The reason for this is that if the scrolling the scroll would move a layer
6994 // that is a drawn RSLL member, then we should accept this hit.
6995 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6996 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6998 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
7001 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
7002 // to CompositorFrameMetadata after SwapBuffers();
7003 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
7004 scoped_ptr
<SolidColorLayerImpl
> root
=
7005 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
7006 root
->SetPosition(gfx::PointF());
7007 root
->SetBounds(gfx::Size(10, 10));
7008 root
->SetDrawsContent(true);
7009 root
->SetHasRenderSurface(true);
7011 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
7013 FakeOutputSurface
* fake_output_surface
=
7014 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
7016 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
7017 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
7018 EXPECT_TRUE(metadata_latency_before
.empty());
7020 ui::LatencyInfo latency_info
;
7021 latency_info
.AddLatencyNumber(
7022 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
7023 scoped_ptr
<SwapPromise
> swap_promise(
7024 new LatencyInfoSwapPromise(latency_info
));
7025 host_impl_
->active_tree()->QueuePinnedSwapPromise(swap_promise
.Pass());
7026 host_impl_
->SetNeedsRedraw();
7028 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
7029 LayerTreeHostImpl::FrameData frame
;
7030 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
7031 host_impl_
->DrawLayers(&frame
);
7032 host_impl_
->DidDrawAllLayers(frame
);
7033 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
7035 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
7036 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
7037 EXPECT_EQ(1u, metadata_latency_after
.size());
7038 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
7039 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
7042 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
7043 int root_layer_id
= 1;
7044 scoped_ptr
<SolidColorLayerImpl
> root
=
7045 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
7046 root
->SetPosition(gfx::PointF());
7047 root
->SetBounds(gfx::Size(10, 10));
7048 root
->SetDrawsContent(true);
7049 root
->SetHasRenderSurface(true);
7051 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
7053 // Ensure the default frame selection bounds are empty.
7054 FakeOutputSurface
* fake_output_surface
=
7055 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
7056 const ViewportSelection
& selection_before
=
7057 fake_output_surface
->last_sent_frame().metadata
.selection
;
7058 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
7059 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
7061 // Plumb the layer-local selection bounds.
7062 gfx::PointF
selection_top(5, 0);
7063 gfx::PointF
selection_bottom(5, 5);
7064 LayerSelection selection
;
7065 selection
.start
.type
= SELECTION_BOUND_CENTER
;
7066 selection
.start
.layer_id
= root_layer_id
;
7067 selection
.start
.edge_bottom
= selection_bottom
;
7068 selection
.start
.edge_top
= selection_top
;
7069 selection
.end
= selection
.start
;
7070 host_impl_
->active_tree()->RegisterSelection(selection
);
7072 // Trigger a draw-swap sequence.
7073 host_impl_
->SetNeedsRedraw();
7075 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
7076 LayerTreeHostImpl::FrameData frame
;
7077 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
7078 host_impl_
->DrawLayers(&frame
);
7079 host_impl_
->DidDrawAllLayers(frame
);
7080 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
7082 // Ensure the selection bounds have propagated to the frame metadata.
7083 const ViewportSelection
& selection_after
=
7084 fake_output_surface
->last_sent_frame().metadata
.selection
;
7085 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
7086 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
7087 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
7088 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
7089 EXPECT_TRUE(selection_after
.start
.visible
);
7090 EXPECT_TRUE(selection_after
.start
.visible
);
7093 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
7095 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
7096 LayerTreeHostImpl
* layer_tree_host_impl
,
7097 int* set_needs_commit_count
,
7098 int* set_needs_redraw_count
,
7099 int* forward_to_main_count
)
7100 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
7101 set_needs_commit_count_(set_needs_commit_count
),
7102 set_needs_redraw_count_(set_needs_redraw_count
),
7103 forward_to_main_count_(forward_to_main_count
) {}
7105 ~SimpleSwapPromiseMonitor() override
{}
7107 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
7109 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
7111 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
7112 (*forward_to_main_count_
)++;
7116 int* set_needs_commit_count_
;
7117 int* set_needs_redraw_count_
;
7118 int* forward_to_main_count_
;
7121 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
7122 int set_needs_commit_count
= 0;
7123 int set_needs_redraw_count
= 0;
7124 int forward_to_main_count
= 0;
7127 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7128 new SimpleSwapPromiseMonitor(NULL
,
7130 &set_needs_commit_count
,
7131 &set_needs_redraw_count
,
7132 &forward_to_main_count
));
7133 host_impl_
->SetNeedsRedraw();
7134 EXPECT_EQ(0, set_needs_commit_count
);
7135 EXPECT_EQ(1, set_needs_redraw_count
);
7136 EXPECT_EQ(0, forward_to_main_count
);
7139 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
7141 host_impl_
->SetNeedsRedraw();
7142 EXPECT_EQ(0, set_needs_commit_count
);
7143 EXPECT_EQ(1, set_needs_redraw_count
);
7144 EXPECT_EQ(0, forward_to_main_count
);
7147 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7148 new SimpleSwapPromiseMonitor(NULL
,
7150 &set_needs_commit_count
,
7151 &set_needs_redraw_count
,
7152 &forward_to_main_count
));
7153 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
7154 EXPECT_EQ(0, set_needs_commit_count
);
7155 EXPECT_EQ(2, set_needs_redraw_count
);
7156 EXPECT_EQ(0, forward_to_main_count
);
7160 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7161 new SimpleSwapPromiseMonitor(NULL
,
7163 &set_needs_commit_count
,
7164 &set_needs_redraw_count
,
7165 &forward_to_main_count
));
7166 // Empty damage rect won't signal the monitor.
7167 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
7168 EXPECT_EQ(0, set_needs_commit_count
);
7169 EXPECT_EQ(2, set_needs_redraw_count
);
7170 EXPECT_EQ(0, forward_to_main_count
);
7174 set_needs_commit_count
= 0;
7175 set_needs_redraw_count
= 0;
7176 forward_to_main_count
= 0;
7177 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
7178 new SimpleSwapPromiseMonitor(NULL
,
7180 &set_needs_commit_count
,
7181 &set_needs_redraw_count
,
7182 &forward_to_main_count
));
7183 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7185 // Scrolling normally should not trigger any forwarding.
7186 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7187 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7189 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7190 host_impl_
->ScrollEnd();
7192 EXPECT_EQ(0, set_needs_commit_count
);
7193 EXPECT_EQ(1, set_needs_redraw_count
);
7194 EXPECT_EQ(0, forward_to_main_count
);
7196 // Scrolling with a scroll handler should defer the swap to the main
7198 scroll_layer
->SetHaveScrollEventHandlers(true);
7199 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7200 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7202 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
7203 host_impl_
->ScrollEnd();
7205 EXPECT_EQ(0, set_needs_commit_count
);
7206 EXPECT_EQ(2, set_needs_redraw_count
);
7207 EXPECT_EQ(1, forward_to_main_count
);
7211 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
7213 void SetUp() override
{
7214 LayerTreeSettings settings
= DefaultSettings();
7215 CreateHostImpl(settings
, CreateOutputSurface());
7216 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
7217 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
7218 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
7222 static const int top_controls_height_
;
7225 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
7227 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
7228 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7229 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7230 BeginFrameArgs begin_frame_args
=
7231 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7232 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7233 host_impl_
->Animate();
7234 EXPECT_FALSE(did_request_redraw_
);
7235 host_impl_
->DidFinishImplFrame();
7238 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
7239 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7240 EXPECT_FALSE(did_request_redraw_
);
7241 host_impl_
->CreatePendingTree();
7242 host_impl_
->sync_tree()->set_top_controls_height(100);
7243 host_impl_
->ActivateSyncTree();
7244 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
7247 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7248 TopControlsStayFullyVisibleOnHeightChange
) {
7249 SetupScrollAndContentsLayers(gfx::Size(100, 100));
7250 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7252 host_impl_
->CreatePendingTree();
7253 host_impl_
->sync_tree()->set_top_controls_height(0);
7254 host_impl_
->ActivateSyncTree();
7255 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7257 host_impl_
->CreatePendingTree();
7258 host_impl_
->sync_tree()->set_top_controls_height(50);
7259 host_impl_
->ActivateSyncTree();
7260 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7263 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
7264 SetupScrollAndContentsLayers(gfx::Size(100, 100))
7265 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
7266 host_impl_
->DidChangeTopControlsPosition();
7267 EXPECT_TRUE(did_request_animate_
);
7268 EXPECT_TRUE(did_request_redraw_
);
7271 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
7272 InputHandlerScrollResult result
;
7273 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7274 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7275 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7276 BOTH
, SHOWN
, false);
7279 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7280 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7281 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7282 EXPECT_EQ(gfx::Vector2dF().ToString(),
7283 scroll_layer
->CurrentScrollOffset().ToString());
7285 // Scroll just the top controls and verify that the scroll succeeds.
7286 const float residue
= 10;
7287 float offset
= top_controls_height_
- residue
;
7288 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7289 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7290 EXPECT_TRUE(result
.did_scroll
);
7291 EXPECT_FLOAT_EQ(-offset
,
7292 host_impl_
->top_controls_manager()->ControlsTopOffset());
7293 EXPECT_EQ(gfx::Vector2dF().ToString(),
7294 scroll_layer
->CurrentScrollOffset().ToString());
7296 // Scroll across the boundary
7297 const float content_scroll
= 20;
7298 offset
= residue
+ content_scroll
;
7299 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7300 EXPECT_TRUE(result
.did_scroll
);
7301 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7302 EXPECT_EQ(-top_controls_height_
,
7303 host_impl_
->top_controls_manager()->ControlsTopOffset());
7304 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
7305 scroll_layer
->CurrentScrollOffset().ToString());
7307 // Now scroll back to the top of the content
7308 offset
= -content_scroll
;
7309 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7310 EXPECT_TRUE(result
.did_scroll
);
7311 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7312 EXPECT_EQ(-top_controls_height_
,
7313 host_impl_
->top_controls_manager()->ControlsTopOffset());
7314 EXPECT_EQ(gfx::Vector2dF().ToString(),
7315 scroll_layer
->CurrentScrollOffset().ToString());
7317 // And scroll the top controls completely into view
7318 offset
= -top_controls_height_
;
7319 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7320 EXPECT_TRUE(result
.did_scroll
);
7321 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, 0));
7322 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7323 EXPECT_EQ(gfx::Vector2dF().ToString(),
7324 scroll_layer
->CurrentScrollOffset().ToString());
7326 // And attempt to scroll past the end
7327 result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
));
7328 EXPECT_FALSE(result
.did_scroll
);
7329 EXPECT_EQ(result
.unused_scroll_delta
, gfx::Vector2d(0, -50));
7330 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7331 EXPECT_EQ(gfx::Vector2dF().ToString(),
7332 scroll_layer
->CurrentScrollOffset().ToString());
7334 host_impl_
->ScrollEnd();
7337 TEST_F(LayerTreeHostImplWithTopControlsTest
, WheelUnhandledByTopControls
) {
7338 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7339 host_impl_
->SetViewportSize(gfx::Size(50, 100));
7340 host_impl_
->active_tree()->set_top_controls_shrink_blink_size(true);
7341 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7345 LayerImpl
* viewport_layer
= host_impl_
->InnerViewportScrollLayer();
7347 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7348 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7349 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7350 EXPECT_VECTOR_EQ(gfx::Vector2dF(), viewport_layer
->CurrentScrollOffset());
7352 // Wheel scrolls should not affect the top controls, and should pass
7353 // directly through to the viewport.
7354 const float delta
= top_controls_height_
;
7356 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7357 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7358 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
),
7359 viewport_layer
->CurrentScrollOffset());
7362 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, delta
)).did_scroll
);
7363 EXPECT_FLOAT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7364 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, delta
* 2),
7365 viewport_layer
->CurrentScrollOffset());
7368 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
7369 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7370 host_impl_
->SetViewportSize(gfx::Size(100, 200));
7371 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7372 BOTH
, SHOWN
, false);
7375 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7376 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7377 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7378 EXPECT_EQ(gfx::Vector2dF().ToString(),
7379 scroll_layer
->CurrentScrollOffset().ToString());
7381 // Scroll the top controls partially.
7382 const float residue
= 35;
7383 float offset
= top_controls_height_
- residue
;
7385 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7386 EXPECT_FLOAT_EQ(-offset
,
7387 host_impl_
->top_controls_manager()->ControlsTopOffset());
7388 EXPECT_EQ(gfx::Vector2dF().ToString(),
7389 scroll_layer
->CurrentScrollOffset().ToString());
7391 did_request_redraw_
= false;
7392 did_request_animate_
= false;
7393 did_request_commit_
= false;
7395 // End the scroll while the controls are still offset from their limit.
7396 host_impl_
->ScrollEnd();
7397 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7398 EXPECT_TRUE(did_request_animate_
);
7399 EXPECT_TRUE(did_request_redraw_
);
7400 EXPECT_FALSE(did_request_commit_
);
7402 // The top controls should properly animate until finished, despite the scroll
7403 // offset being at the origin.
7404 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7405 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7406 while (did_request_animate_
) {
7407 did_request_redraw_
= false;
7408 did_request_animate_
= false;
7409 did_request_commit_
= false;
7412 host_impl_
->top_controls_manager()->ControlsTopOffset();
7414 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7415 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7416 host_impl_
->Animate();
7417 EXPECT_EQ(gfx::Vector2dF().ToString(),
7418 scroll_layer
->CurrentScrollOffset().ToString());
7421 host_impl_
->top_controls_manager()->ControlsTopOffset();
7423 // No commit is needed as the controls are animating the content offset,
7424 // not the scroll offset.
7425 EXPECT_FALSE(did_request_commit_
);
7427 if (new_offset
!= old_offset
)
7428 EXPECT_TRUE(did_request_redraw_
);
7430 if (new_offset
!= 0) {
7431 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
7432 EXPECT_TRUE(did_request_animate_
);
7434 host_impl_
->DidFinishImplFrame();
7436 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7439 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
7440 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7441 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7442 host_impl_
->top_controls_manager()->UpdateTopControlsState(
7443 BOTH
, SHOWN
, false);
7444 float initial_scroll_offset
= 50;
7445 scroll_layer
->PushScrollOffsetFromMainThread(
7446 gfx::ScrollOffset(0, initial_scroll_offset
));
7449 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7450 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7451 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7452 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7453 scroll_layer
->CurrentScrollOffset().ToString());
7455 // Scroll the top controls partially.
7456 const float residue
= 15;
7457 float offset
= top_controls_height_
- residue
;
7459 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7460 EXPECT_FLOAT_EQ(-offset
,
7461 host_impl_
->top_controls_manager()->ControlsTopOffset());
7462 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7463 scroll_layer
->CurrentScrollOffset().ToString());
7465 did_request_redraw_
= false;
7466 did_request_animate_
= false;
7467 did_request_commit_
= false;
7469 // End the scroll while the controls are still offset from the limit.
7470 host_impl_
->ScrollEnd();
7471 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7472 EXPECT_TRUE(did_request_animate_
);
7473 EXPECT_TRUE(did_request_redraw_
);
7474 EXPECT_FALSE(did_request_commit_
);
7476 // Animate the top controls to the limit.
7477 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7478 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7479 while (did_request_animate_
) {
7480 did_request_redraw_
= false;
7481 did_request_animate_
= false;
7482 did_request_commit_
= false;
7485 host_impl_
->top_controls_manager()->ControlsTopOffset();
7487 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7488 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7489 host_impl_
->Animate();
7492 host_impl_
->top_controls_manager()->ControlsTopOffset();
7494 if (new_offset
!= old_offset
) {
7495 EXPECT_TRUE(did_request_redraw_
);
7496 EXPECT_TRUE(did_request_commit_
);
7498 host_impl_
->DidFinishImplFrame();
7500 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7501 EXPECT_EQ(-top_controls_height_
,
7502 host_impl_
->top_controls_manager()->ControlsTopOffset());
7505 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7506 TopControlsAnimationAfterMainThreadFlingStopped
) {
7507 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7508 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7509 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7511 float initial_scroll_offset
= 50;
7512 scroll_layer
->PushScrollOffsetFromMainThread(
7513 gfx::ScrollOffset(0, initial_scroll_offset
));
7516 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7517 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7518 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7519 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7520 scroll_layer
->CurrentScrollOffset().ToString());
7522 // Scroll the top controls partially.
7523 const float residue
= 15;
7524 float offset
= top_controls_height_
- residue
;
7526 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7527 EXPECT_FLOAT_EQ(-offset
,
7528 host_impl_
->top_controls_manager()->ControlsTopOffset());
7529 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7530 scroll_layer
->CurrentScrollOffset().ToString());
7532 did_request_redraw_
= false;
7533 did_request_animate_
= false;
7534 did_request_commit_
= false;
7536 // End the fling while the controls are still offset from the limit.
7537 host_impl_
->MainThreadHasStoppedFlinging();
7538 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7539 EXPECT_TRUE(did_request_animate_
);
7540 EXPECT_TRUE(did_request_redraw_
);
7541 EXPECT_FALSE(did_request_commit_
);
7543 // Animate the top controls to the limit.
7544 BeginFrameArgs begin_frame_args
= CreateBeginFrameArgsForTesting(
7545 BEGINFRAME_FROM_HERE
, base::TimeTicks::Now());
7546 while (did_request_animate_
) {
7547 did_request_redraw_
= false;
7548 did_request_animate_
= false;
7549 did_request_commit_
= false;
7551 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7553 begin_frame_args
.frame_time
+= base::TimeDelta::FromMilliseconds(5);
7554 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7555 host_impl_
->Animate();
7557 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7559 if (new_offset
!= old_offset
) {
7560 EXPECT_TRUE(did_request_redraw_
);
7561 EXPECT_TRUE(did_request_commit_
);
7563 host_impl_
->DidFinishImplFrame();
7565 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7566 EXPECT_EQ(-top_controls_height_
,
7567 host_impl_
->top_controls_manager()->ControlsTopOffset());
7570 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7571 TopControlsScrollDeltaInOverScroll
) {
7572 // Verifies that the overscroll delta should not have accumulated in
7573 // the top controls if we do a hide and show without releasing finger.
7575 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7576 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7577 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7581 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7582 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7583 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7587 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7588 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7589 EXPECT_EQ(gfx::Vector2dF().ToString(),
7590 scroll_layer
->CurrentScrollOffset().ToString());
7593 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7594 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7595 scroll_layer
->CurrentScrollOffset().ToString());
7598 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7600 // Should have fully scrolled
7601 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7602 scroll_layer
->CurrentScrollOffset().ToString());
7604 float overscrollamount
= 10;
7606 // Overscroll the content
7608 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7610 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7611 scroll_layer
->CurrentScrollOffset().ToString());
7612 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7613 host_impl_
->accumulated_root_overscroll().ToString());
7615 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7617 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7618 scroll_layer
->CurrentScrollOffset().ToString());
7619 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7622 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7623 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7624 scroll_layer
->CurrentScrollOffset().ToString());
7626 // Top controls should be fully visible
7627 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7629 host_impl_
->ScrollEnd();
7632 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7634 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7635 const gfx::Size
& outer_viewport
,
7636 const gfx::Size
& inner_viewport
) {
7637 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7638 const int kOuterViewportClipLayerId
= 6;
7639 const int kOuterViewportScrollLayerId
= 7;
7640 const int kInnerViewportScrollLayerId
= 2;
7641 const int kInnerViewportClipLayerId
= 4;
7642 const int kPageScaleLayerId
= 5;
7644 scoped_ptr
<LayerImpl
> inner_scroll
=
7645 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7646 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7647 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7649 scoped_ptr
<LayerImpl
> inner_clip
=
7650 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7651 inner_clip
->SetBounds(inner_viewport
);
7653 scoped_ptr
<LayerImpl
> page_scale
=
7654 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7656 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7657 inner_scroll
->SetBounds(outer_viewport
);
7658 inner_scroll
->SetPosition(gfx::PointF());
7660 scoped_ptr
<LayerImpl
> outer_clip
=
7661 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7662 outer_clip
->SetBounds(outer_viewport
);
7663 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7665 scoped_ptr
<LayerImpl
> outer_scroll
=
7666 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7667 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7668 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7669 outer_scroll
->SetBounds(content_size
);
7670 outer_scroll
->SetPosition(gfx::PointF());
7672 scoped_ptr
<LayerImpl
> contents
=
7673 LayerImpl::Create(layer_tree_impl
, 8);
7674 contents
->SetDrawsContent(true);
7675 contents
->SetBounds(content_size
);
7676 contents
->SetPosition(gfx::PointF());
7678 outer_scroll
->AddChild(contents
.Pass());
7679 outer_clip
->AddChild(outer_scroll
.Pass());
7680 inner_scroll
->AddChild(outer_clip
.Pass());
7681 page_scale
->AddChild(inner_scroll
.Pass());
7682 inner_clip
->AddChild(page_scale
.Pass());
7684 inner_clip
->SetHasRenderSurface(true);
7685 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7686 layer_tree_impl
->SetViewportLayersFromIds(
7687 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7688 kOuterViewportScrollLayerId
);
7690 host_impl_
->active_tree()->DidBecomeActive();
7694 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7695 gfx::Size content_size
= gfx::Size(100, 160);
7696 gfx::Size outer_viewport
= gfx::Size(50, 80);
7697 gfx::Size inner_viewport
= gfx::Size(25, 40);
7699 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7701 TestScrollOffsetDelegate scroll_delegate
;
7702 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7704 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7705 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7708 gfx::ScrollOffset inner_expected
;
7709 gfx::ScrollOffset outer_expected
;
7710 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7711 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7713 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7715 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged(current_offset
);
7716 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7717 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7719 // Outer viewport scrolls first. Then the rest is applied to the inner
7721 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7722 inner_scroll
->CurrentScrollOffset());
7723 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7724 outer_scroll
->CurrentScrollOffset());
7728 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7729 gfx::Size content_size
= gfx::Size(200, 320);
7730 gfx::Size outer_viewport
= gfx::Size(100, 160);
7731 gfx::Size inner_viewport
= gfx::Size(50, 80);
7733 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7735 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7736 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7739 gfx::Vector2dF inner_expected
;
7740 gfx::Vector2dF outer_expected
;
7741 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7742 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7744 // Scrolling the viewport always sets the outer scroll layer as the
7745 // currently scrolling layer.
7746 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7747 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7748 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7749 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7750 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7752 gfx::Vector2d
scroll_delta(inner_viewport
.width() / 2.f
,
7753 inner_viewport
.height() / 2.f
);
7754 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7755 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7756 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), outer_scroll
);
7758 host_impl_
->ScrollEnd();
7759 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7761 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7762 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7764 // Fling past the inner viewport boundry, make sure outer viewport scrolls.
7765 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7766 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7767 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7768 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7769 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7771 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7772 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7773 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7775 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7776 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7777 EXPECT_EQ(outer_scroll
, host_impl_
->CurrentlyScrollingLayer());
7779 host_impl_
->ScrollEnd();
7780 EXPECT_EQ(nullptr, host_impl_
->CurrentlyScrollingLayer());
7782 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7783 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7787 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7788 DiagonalScrollBubblesPerfectlyToInner
) {
7789 gfx::Size content_size
= gfx::Size(200, 320);
7790 gfx::Size outer_viewport
= gfx::Size(100, 160);
7791 gfx::Size inner_viewport
= gfx::Size(50, 80);
7793 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7795 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7796 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7799 gfx::Vector2dF inner_expected
;
7800 gfx::Vector2dF outer_expected
;
7801 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7802 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7804 // Make sure the scroll goes to the inner viewport first.
7805 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7806 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7807 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7808 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7809 InputHandler::GESTURE
));
7811 // Scroll near the edge of the outer viewport.
7812 gfx::Vector2d
scroll_delta(inner_viewport
.width() / 2.f
,
7813 inner_viewport
.height() / 2.f
);
7814 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7815 inner_expected
+= scroll_delta
;
7816 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7817 InputHandler::GESTURE
));
7819 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7820 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7822 // Now diagonal scroll across the outer viewport boundary in a single event.
7823 // The entirety of the scroll should be consumed, as bubbling between inner
7824 // and outer viewport layers is perfect.
7825 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7826 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7827 InputHandler::GESTURE
));
7828 outer_expected
+= scroll_delta
;
7829 inner_expected
+= scroll_delta
;
7830 host_impl_
->ScrollEnd();
7831 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7832 gfx::Point(), InputHandler::GESTURE
));
7834 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7835 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7839 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7840 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7841 gfx::Size content_size
= gfx::Size(100, 160);
7842 gfx::Size outer_viewport
= gfx::Size(50, 80);
7843 gfx::Size inner_viewport
= gfx::Size(25, 40);
7845 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7847 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7848 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7850 scoped_ptr
<LayerImpl
> child
=
7851 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7852 LayerImpl
* child_scroll
= child
.get();
7853 outer_scroll
->children()[0]->AddChild(child
.Pass());
7857 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7859 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7860 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7861 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7862 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7863 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7864 InputHandler::GESTURE
));
7866 // The child should have scrolled up to its limit.
7867 scroll_info
= host_impl_
->ProcessScrollDeltas();
7868 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7870 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7871 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7873 // The first |ScrollBy| after the fling should re-lock the scrolling
7874 // layer to the first layer that scrolled, the inner viewport scroll layer.
7875 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7876 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7877 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7878 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7879 InputHandler::GESTURE
));
7881 // The inner viewport should have scrolled up to its limit.
7882 scroll_info
= host_impl_
->ProcessScrollDeltas();
7883 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7885 ScrollInfoContains(*scroll_info
, child_scroll
->id(), scroll_delta
));
7887 ScrollInfoContains(*scroll_info
, inner_scroll
->id(), scroll_delta
));
7889 // As the locked layer is at its limit, no further scrolling can occur.
7890 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7891 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7892 host_impl_
->ScrollEnd();
7893 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7894 gfx::Point(), InputHandler::GESTURE
));
7898 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7899 ScrollBeginEventThatTargetsViewportLayerSkipsHitTest
) {
7900 gfx::Size content_size
= gfx::Size(100, 160);
7901 gfx::Size outer_viewport
= gfx::Size(50, 80);
7902 gfx::Size inner_viewport
= gfx::Size(25, 40);
7904 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7906 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7907 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7909 scoped_ptr
<LayerImpl
> child
=
7910 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7911 LayerImpl
* child_scroll
= child
.get();
7912 outer_scroll
->children()[0]->AddChild(child
.Pass());
7916 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7917 host_impl_
->RootScrollBegin(InputHandler::GESTURE
));
7918 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7919 host_impl_
->ScrollEnd();
7920 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7921 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7922 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7923 host_impl_
->ScrollEnd();
7926 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7927 NoOverscrollWhenInnerViewportCantScroll
) {
7928 InputHandlerScrollResult scroll_result
;
7929 gfx::Size content_size
= gfx::Size(100, 160);
7930 gfx::Size outer_viewport
= gfx::Size(50, 80);
7931 gfx::Size inner_viewport
= gfx::Size(25, 40);
7932 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7935 // Make inner viewport unscrollable.
7936 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7937 inner_scroll
->set_user_scrollable_horizontal(false);
7938 inner_scroll
->set_user_scrollable_vertical(false);
7940 // Ensure inner viewport doesn't react to scrolls (test it's unscrollable).
7941 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7942 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7943 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7944 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
7945 EXPECT_VECTOR_EQ(gfx::Vector2dF(), inner_scroll
->CurrentScrollOffset());
7947 // When inner viewport is unscrollable, a fling gives zero overscroll.
7948 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
7949 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
7952 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7954 void SetUp() override
{
7955 LayerTreeSettings settings
= DefaultSettings();
7956 settings
.max_memory_for_prepaint_percentage
= 50;
7957 CreateHostImpl(settings
, CreateOutputSurface());
7961 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7962 // Set up a memory policy and percentages which could cause
7963 // 32-bit integer overflows.
7964 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7966 // Verify implicit limits are calculated correctly with no overflows
7967 host_impl_
->SetMemoryPolicy(mem_policy
);
7968 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7969 300u * 1024u * 1024u);
7970 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7971 150u * 1024u * 1024u);
7974 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7975 const gfx::Size
layer_size(100, 100);
7976 gfx::Transform external_transform
;
7977 const gfx::Rect
external_viewport(layer_size
);
7978 const gfx::Rect
external_clip(layer_size
);
7979 const bool resourceless_software_draw
= false;
7980 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7982 host_impl_
->SetExternalDrawConstraints(external_transform
,
7987 resourceless_software_draw
);
7989 EXPECT_TRANSFORMATION_MATRIX_EQ(
7990 external_transform
, layer
->draw_properties().target_space_transform
);
7992 external_transform
.Translate(20, 20);
7993 host_impl_
->SetExternalDrawConstraints(external_transform
,
7998 resourceless_software_draw
);
8000 EXPECT_TRANSFORMATION_MATRIX_EQ(
8001 external_transform
, layer
->draw_properties().target_space_transform
);
8004 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
8005 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8008 base::TimeTicks start_time
=
8009 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8011 BeginFrameArgs begin_frame_args
=
8012 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8014 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8015 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8017 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
8019 begin_frame_args
.frame_time
= start_time
;
8020 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8021 host_impl_
->Animate();
8022 host_impl_
->UpdateAnimationState(true);
8024 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
8025 host_impl_
->DidFinishImplFrame();
8027 begin_frame_args
.frame_time
=
8028 start_time
+ base::TimeDelta::FromMilliseconds(50);
8029 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8030 host_impl_
->Animate();
8031 host_impl_
->UpdateAnimationState(true);
8033 float y
= scrolling_layer
->CurrentScrollOffset().y();
8034 EXPECT_TRUE(y
> 1 && y
< 49);
8037 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8038 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8039 host_impl_
->DidFinishImplFrame();
8041 begin_frame_args
.frame_time
=
8042 start_time
+ base::TimeDelta::FromMilliseconds(200);
8043 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8044 host_impl_
->Animate();
8045 host_impl_
->UpdateAnimationState(true);
8047 y
= scrolling_layer
->CurrentScrollOffset().y();
8048 EXPECT_TRUE(y
> 50 && y
< 100);
8049 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
8050 host_impl_
->DidFinishImplFrame();
8052 begin_frame_args
.frame_time
=
8053 start_time
+ base::TimeDelta::FromMilliseconds(250);
8054 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8055 host_impl_
->Animate();
8056 host_impl_
->UpdateAnimationState(true);
8058 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8059 scrolling_layer
->CurrentScrollOffset());
8060 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
8061 host_impl_
->DidFinishImplFrame();
8064 // Evolved from LayerTreeHostImplTest.ScrollAnimated.
8065 TEST_F(LayerTreeHostImplTimelinesTest
, ScrollAnimated
) {
8066 SetupScrollAndContentsLayers(gfx::Size(100, 200));
8069 base::TimeTicks start_time
=
8070 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
8072 BeginFrameArgs begin_frame_args
=
8073 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8075 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8076 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8078 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
8080 begin_frame_args
.frame_time
= start_time
;
8081 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8082 host_impl_
->Animate();
8083 host_impl_
->UpdateAnimationState(true);
8085 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
8086 host_impl_
->DidFinishImplFrame();
8088 begin_frame_args
.frame_time
=
8089 start_time
+ base::TimeDelta::FromMilliseconds(50);
8090 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8091 host_impl_
->Animate();
8092 host_impl_
->UpdateAnimationState(true);
8094 float y
= scrolling_layer
->CurrentScrollOffset().y();
8095 EXPECT_TRUE(y
> 1 && y
< 49);
8098 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8099 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
8100 host_impl_
->DidFinishImplFrame();
8102 begin_frame_args
.frame_time
=
8103 start_time
+ base::TimeDelta::FromMilliseconds(200);
8104 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8105 host_impl_
->Animate();
8106 host_impl_
->UpdateAnimationState(true);
8108 y
= scrolling_layer
->CurrentScrollOffset().y();
8109 EXPECT_TRUE(y
> 50 && y
< 100);
8110 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
8111 host_impl_
->DidFinishImplFrame();
8113 begin_frame_args
.frame_time
=
8114 start_time
+ base::TimeDelta::FromMilliseconds(250);
8115 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8116 host_impl_
->Animate();
8117 host_impl_
->UpdateAnimationState(true);
8119 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
8120 scrolling_layer
->CurrentScrollOffset());
8121 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
8122 host_impl_
->DidFinishImplFrame();
8125 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
8126 host_impl_
->CreatePendingTree();
8128 Region empty_invalidation
;
8129 scoped_refptr
<RasterSource
> pile_with_tiles(
8130 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
8131 gfx::Size(10, 10)));
8133 scoped_ptr
<FakePictureLayerImpl
> layer
=
8134 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
8135 layer
->SetBounds(gfx::Size(10, 10));
8136 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
8137 layer
->SetDrawsContent(true);
8138 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
8139 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
8140 layer
->tilings()->tiling_at(0)->set_resolution(
8141 TileResolution::HIGH_RESOLUTION
);
8142 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
8143 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
8144 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
8145 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
8147 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
8148 host_impl_
->pending_tree()->root_layer());
8150 root_layer
->set_has_valid_tile_priorities(true);
8151 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
8152 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8153 RasterTilePriorityQueue::Type::ALL
);
8154 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
8156 root_layer
->set_has_valid_tile_priorities(false);
8157 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
8158 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
8159 RasterTilePriorityQueue::Type::ALL
);
8160 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
8163 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
8164 host_impl_
->CreatePendingTree();
8165 host_impl_
->ActivateSyncTree();
8166 host_impl_
->CreatePendingTree();
8168 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
8170 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
8171 FakePictureLayerImpl::Create(pending_tree
, 10);
8172 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
8173 pending_tree
->SetRootLayer(pending_layer
.Pass());
8174 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
8176 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
8177 pending_tree
->DidBecomeActive();
8178 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8180 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
8181 FakePictureLayerImpl::Create(pending_tree
, 11);
8182 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
8183 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
8184 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
8186 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
8187 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
8188 pending_tree
->DidBecomeActive();
8189 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8190 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8192 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
8193 FakePictureLayerImpl::Create(pending_tree
, 12);
8194 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
8195 FakePictureLayerImpl::Create(pending_tree
, 13);
8196 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
8197 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
8198 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
8199 ASSERT_EQ(raw_replica_mask_layer
,
8200 raw_pending_layer
->replica_layer()->mask_layer());
8202 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
8203 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
8204 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
8205 pending_tree
->DidBecomeActive();
8206 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
8207 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
8208 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
8211 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
8212 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
8213 host_impl_
->SetViewportSize(gfx::Size(50, 50));
8216 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
8218 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
8219 float page_scale_factor
= 1.f
;
8221 // The scroll deltas should have the page scale factor applied.
8223 host_impl_
->active_tree()->PushPageScaleFromMainThread(
8224 page_scale_factor
, min_page_scale
, max_page_scale
);
8225 host_impl_
->active_tree()->SetPageScaleOnActiveTree(page_scale_factor
);
8226 scroll_layer
->SetScrollDelta(gfx::Vector2d());
8228 float page_scale_delta
= 2.f
;
8229 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
8230 host_impl_
->PinchGestureBegin();
8231 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
8232 host_impl_
->PinchGestureEnd();
8233 host_impl_
->ScrollEnd();
8235 gfx::Vector2dF
scroll_delta(0, 5);
8236 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
8237 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
8238 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
8240 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
8241 host_impl_
->ScrollEnd();
8242 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
8243 scroll_layer
->CurrentScrollOffset());
8247 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
8249 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
8250 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
8253 int num_lost_surfaces_
;
8256 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
8257 // Really we just need at least one client notification each time
8258 // we go from having a valid output surface to not having a valid output
8260 EXPECT_EQ(0, num_lost_surfaces_
);
8261 host_impl_
->DidLoseOutputSurface();
8262 EXPECT_EQ(1, num_lost_surfaces_
);
8263 host_impl_
->DidLoseOutputSurface();
8264 EXPECT_LE(1, num_lost_surfaces_
);
8267 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
8268 LayerTreeHostImpl::FrameData frame
;
8269 frame
.render_passes
.push_back(RenderPass::Create());
8270 RenderPass
* pass3
= frame
.render_passes
.back();
8271 frame
.render_passes
.push_back(RenderPass::Create());
8272 RenderPass
* pass2
= frame
.render_passes
.back();
8273 frame
.render_passes
.push_back(RenderPass::Create());
8274 RenderPass
* pass1
= frame
.render_passes
.back();
8276 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8277 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8278 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8280 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8281 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8282 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8284 // Add a quad to each pass so they aren't empty.
8285 SolidColorDrawQuad
* color_quad
;
8286 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8287 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8288 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8289 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8290 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8291 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8293 // pass3 is referenced by pass2.
8294 RenderPassDrawQuad
* rpdq
=
8295 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8296 rpdq
->material
= DrawQuad::RENDER_PASS
;
8297 rpdq
->render_pass_id
= pass3
->id
;
8299 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
8300 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8301 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8302 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8303 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8304 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8305 EXPECT_EQ(1u, frame
.render_passes
.size());
8306 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8309 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
8310 LayerTreeHostImpl::FrameData frame
;
8311 frame
.render_passes
.push_back(RenderPass::Create());
8312 RenderPass
* pass3
= frame
.render_passes
.back();
8313 frame
.render_passes
.push_back(RenderPass::Create());
8314 RenderPass
* pass2
= frame
.render_passes
.back();
8315 frame
.render_passes
.push_back(RenderPass::Create());
8316 RenderPass
* pass1
= frame
.render_passes
.back();
8318 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8319 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8320 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8322 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8323 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8324 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8326 // pass1 is not empty, but pass2 and pass3 are.
8327 SolidColorDrawQuad
* color_quad
;
8328 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
8329 color_quad
->material
= DrawQuad::SOLID_COLOR
;
8331 // pass3 is referenced by pass2.
8332 RenderPassDrawQuad
* rpdq
=
8333 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8334 rpdq
->material
= DrawQuad::RENDER_PASS
;
8335 rpdq
->render_pass_id
= pass3
->id
;
8337 // pass2 is referenced by pass1.
8338 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8339 rpdq
->material
= DrawQuad::RENDER_PASS
;
8340 rpdq
->render_pass_id
= pass2
->id
;
8342 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8343 // should be removed.
8344 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8345 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8346 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8347 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8348 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8349 EXPECT_EQ(1u, frame
.render_passes
.size());
8350 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8351 // The RenderPassDrawQuad should be removed from pass1.
8352 EXPECT_EQ(1u, pass1
->quad_list
.size());
8353 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
8356 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
8357 LayerTreeHostImpl::FrameData frame
;
8358 frame
.render_passes
.push_back(RenderPass::Create());
8359 RenderPass
* pass3
= frame
.render_passes
.back();
8360 frame
.render_passes
.push_back(RenderPass::Create());
8361 RenderPass
* pass2
= frame
.render_passes
.back();
8362 frame
.render_passes
.push_back(RenderPass::Create());
8363 RenderPass
* pass1
= frame
.render_passes
.back();
8365 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8366 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8367 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
8369 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
8370 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
8371 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
8373 // pass3 is referenced by pass2.
8374 RenderPassDrawQuad
* rpdq
=
8375 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8376 rpdq
->material
= DrawQuad::RENDER_PASS
;
8377 rpdq
->render_pass_id
= pass3
->id
;
8379 // pass2 is referenced by pass1.
8380 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
8381 rpdq
->material
= DrawQuad::RENDER_PASS
;
8382 rpdq
->render_pass_id
= pass2
->id
;
8384 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
8385 // should be removed. Then pass1 is empty too, but it's the root so it should
8387 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
8388 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
8389 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
8390 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
8391 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
8392 EXPECT_EQ(1u, frame
.render_passes
.size());
8393 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
8394 // The RenderPassDrawQuad should be removed from pass1.
8395 EXPECT_EQ(0u, pass1
->quad_list
.size());
8398 class FakeVideoFrameController
: public VideoFrameController
{
8400 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
8401 begin_frame_args_
= args
;
8402 did_draw_frame_
= false;
8405 void DidDrawFrame() override
{ did_draw_frame_
= true; }
8407 const BeginFrameArgs
& begin_frame_args() const { return begin_frame_args_
; }
8409 bool did_draw_frame() const { return did_draw_frame_
; }
8412 BeginFrameArgs begin_frame_args_
;
8413 bool did_draw_frame_
= false;
8416 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
8417 BeginFrameArgs begin_frame_args
=
8418 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8419 FakeVideoFrameController controller
;
8421 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8422 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8423 host_impl_
->AddVideoFrameController(&controller
);
8424 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8425 host_impl_
->DidFinishImplFrame();
8427 EXPECT_FALSE(controller
.did_draw_frame());
8428 LayerTreeHostImpl::FrameData frame
;
8429 host_impl_
->DidDrawAllLayers(frame
);
8430 EXPECT_TRUE(controller
.did_draw_frame());
8432 controller
.OnBeginFrame(begin_frame_args
);
8433 EXPECT_FALSE(controller
.did_draw_frame());
8434 host_impl_
->RemoveVideoFrameController(&controller
);
8435 host_impl_
->DidDrawAllLayers(frame
);
8436 EXPECT_FALSE(controller
.did_draw_frame());
8439 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
8440 BeginFrameArgs begin_frame_args
=
8441 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8442 FakeVideoFrameController controller
;
8444 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8445 host_impl_
->DidFinishImplFrame();
8447 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8448 host_impl_
->AddVideoFrameController(&controller
);
8449 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8451 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
8452 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
8453 host_impl_
->WillBeginImplFrame(begin_frame_args
);
8454 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
8456 EXPECT_FALSE(controller
.did_draw_frame());
8457 LayerTreeHostImpl::FrameData frame
;
8458 host_impl_
->DidDrawAllLayers(frame
);
8459 EXPECT_TRUE(controller
.did_draw_frame());
8461 controller
.OnBeginFrame(begin_frame_args
);
8462 EXPECT_FALSE(controller
.did_draw_frame());
8463 host_impl_
->RemoveVideoFrameController(&controller
);
8464 host_impl_
->DidDrawAllLayers(frame
);
8465 EXPECT_FALSE(controller
.did_draw_frame());
8468 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
8469 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8471 host_impl_
->SetHasGpuRasterizationTrigger(true);
8472 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8473 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
8474 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8476 host_impl_
->SetHasGpuRasterizationTrigger(false);
8477 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8478 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
8479 host_impl_
->gpu_rasterization_status());
8480 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8482 host_impl_
->SetHasGpuRasterizationTrigger(true);
8483 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8484 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
8485 host_impl_
->gpu_rasterization_status());
8486 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8487 EXPECT_FALSE(host_impl_
->use_msaa());
8489 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
8490 TestWebGraphicsContext3D::Create();
8491 context_with_msaa
->SetMaxSamples(8);
8493 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
8494 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
8495 EXPECT_TRUE(CreateHostImpl(
8496 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
8497 host_impl_
->SetHasGpuRasterizationTrigger(true);
8498 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8499 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
8500 host_impl_
->gpu_rasterization_status());
8501 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8502 EXPECT_TRUE(host_impl_
->use_msaa());
8504 LayerTreeSettings settings
= DefaultSettings();
8505 settings
.gpu_rasterization_enabled
= false;
8506 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8507 host_impl_
->SetHasGpuRasterizationTrigger(true);
8508 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
8509 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
8510 host_impl_
->gpu_rasterization_status());
8511 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
8513 settings
.gpu_rasterization_forced
= true;
8514 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
8516 host_impl_
->SetHasGpuRasterizationTrigger(false);
8517 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
8518 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
8519 host_impl_
->gpu_rasterization_status());
8520 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
8523 // A mock output surface which lets us detect calls to ForceReclaimResources.
8524 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
8526 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
8527 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
8528 TestContextProvider::Create(), TestContextProvider::Create(), false));
8531 MOCK_METHOD0(ForceReclaimResources
, void());
8534 MockReclaimResourcesOutputSurface(
8535 scoped_refptr
<ContextProvider
> context_provider
,
8536 scoped_refptr
<ContextProvider
> worker_context_provider
,
8537 bool delegated_rendering
)
8538 : FakeOutputSurface(context_provider
,
8539 worker_context_provider
,
8540 delegated_rendering
) {}
8543 // Display::Draw (and the planned Display Scheduler) currently rely on resources
8544 // being reclaimed to block drawing between BeginCommit / Swap. This test
8545 // ensures that BeginCommit triggers ForceReclaimResources. See
8546 // crbug.com/489515.
8547 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
8548 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
8549 MockReclaimResourcesOutputSurface::Create3d());
8550 // Hold an unowned pointer to the output surface to use for mock expectations.
8551 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
8553 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
8554 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
8555 host_impl_
->BeginCommit();