1 // Copyright 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/trees/layer_tree_host_impl.h"
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/containers/hash_tables.h"
13 #include "base/containers/scoped_ptr_hash_map.h"
14 #include "base/location.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "cc/animation/scrollbar_animation_controller_thinning.h"
17 #include "cc/base/math_util.h"
18 #include "cc/input/page_scale_animation.h"
19 #include "cc/input/top_controls_manager.h"
20 #include "cc/layers/append_quads_data.h"
21 #include "cc/layers/delegated_renderer_layer_impl.h"
22 #include "cc/layers/heads_up_display_layer_impl.h"
23 #include "cc/layers/io_surface_layer_impl.h"
24 #include "cc/layers/layer_impl.h"
25 #include "cc/layers/painted_scrollbar_layer_impl.h"
26 #include "cc/layers/render_surface_impl.h"
27 #include "cc/layers/solid_color_layer_impl.h"
28 #include "cc/layers/solid_color_scrollbar_layer_impl.h"
29 #include "cc/layers/texture_layer_impl.h"
30 #include "cc/layers/tiled_layer_impl.h"
31 #include "cc/layers/video_layer_impl.h"
32 #include "cc/output/begin_frame_args.h"
33 #include "cc/output/compositor_frame_ack.h"
34 #include "cc/output/compositor_frame_metadata.h"
35 #include "cc/output/copy_output_request.h"
36 #include "cc/output/copy_output_result.h"
37 #include "cc/output/gl_renderer.h"
38 #include "cc/output/latency_info_swap_promise.h"
39 #include "cc/quads/render_pass_draw_quad.h"
40 #include "cc/quads/solid_color_draw_quad.h"
41 #include "cc/quads/texture_draw_quad.h"
42 #include "cc/quads/tile_draw_quad.h"
43 #include "cc/test/animation_test_common.h"
44 #include "cc/test/begin_frame_args_test.h"
45 #include "cc/test/fake_layer_tree_host_impl.h"
46 #include "cc/test/fake_output_surface.h"
47 #include "cc/test/fake_output_surface_client.h"
48 #include "cc/test/fake_picture_layer_impl.h"
49 #include "cc/test/fake_picture_pile_impl.h"
50 #include "cc/test/fake_proxy.h"
51 #include "cc/test/fake_video_frame_provider.h"
52 #include "cc/test/geometry_test_utils.h"
53 #include "cc/test/gpu_rasterization_enabled_settings.h"
54 #include "cc/test/layer_test_common.h"
55 #include "cc/test/layer_tree_test.h"
56 #include "cc/test/render_pass_test_common.h"
57 #include "cc/test/test_gpu_memory_buffer_manager.h"
58 #include "cc/test/test_shared_bitmap_manager.h"
59 #include "cc/test/test_task_graph_runner.h"
60 #include "cc/test/test_web_graphics_context_3d.h"
61 #include "cc/tiles/layer_tiling_data.h"
62 #include "cc/trees/layer_tree_impl.h"
63 #include "cc/trees/single_thread_proxy.h"
64 #include "media/base/media.h"
65 #include "testing/gmock/include/gmock/gmock.h"
66 #include "testing/gtest/include/gtest/gtest.h"
67 #include "third_party/skia/include/core/SkMallocPixelRef.h"
68 #include "ui/gfx/geometry/rect_conversions.h"
69 #include "ui/gfx/geometry/size_conversions.h"
70 #include "ui/gfx/geometry/vector2d_conversions.h"
72 using ::testing::Mock
;
73 using ::testing::Return
;
74 using ::testing::AnyNumber
;
75 using ::testing::AtLeast
;
77 using media::VideoFrame
;
82 class LayerTreeHostImplTest
: public testing::Test
,
83 public LayerTreeHostImplClient
{
85 LayerTreeHostImplTest()
86 : proxy_(base::ThreadTaskRunnerHandle::Get(),
87 base::ThreadTaskRunnerHandle::Get()),
88 always_impl_thread_(&proxy_
),
89 always_main_thread_blocked_(&proxy_
),
90 shared_bitmap_manager_(new TestSharedBitmapManager
),
91 gpu_memory_buffer_manager_(new TestGpuMemoryBufferManager
),
92 task_graph_runner_(new TestTaskGraphRunner
),
93 on_can_draw_state_changed_called_(false),
94 did_notify_ready_to_activate_(false),
95 did_request_commit_(false),
96 did_request_redraw_(false),
97 did_request_animate_(false),
98 did_request_prepare_tiles_(false),
99 did_complete_page_scale_animation_(false),
100 reduce_memory_result_(true),
101 current_limit_bytes_(0),
102 current_priority_cutoff_value_(0) {
103 media::InitializeMediaLibraryForTesting();
106 LayerTreeSettings
DefaultSettings() {
107 LayerTreeSettings settings
;
108 settings
.minimum_occlusion_tracking_size
= gfx::Size();
109 settings
.impl_side_painting
= true;
110 settings
.renderer_settings
.texture_id_allocation_chunk_size
= 1;
111 settings
.report_overscroll_only_for_scrollable_axes
= true;
112 settings
.gpu_rasterization_enabled
= true;
116 void SetUp() override
{
117 CreateHostImpl(DefaultSettings(), CreateOutputSurface());
120 void TearDown() override
{}
122 void UpdateRendererCapabilitiesOnImplThread() override
{}
123 void DidLoseOutputSurfaceOnImplThread() override
{}
124 void CommitVSyncParameters(base::TimeTicks timebase
,
125 base::TimeDelta interval
) override
{}
126 void SetEstimatedParentDrawTime(base::TimeDelta draw_time
) override
{}
127 void SetMaxSwapsPendingOnImplThread(int max
) override
{}
128 void DidSwapBuffersOnImplThread() override
{}
129 void DidSwapBuffersCompleteOnImplThread() override
{}
130 void OnCanDrawStateChanged(bool can_draw
) override
{
131 on_can_draw_state_changed_called_
= true;
133 void NotifyReadyToActivate() override
{
134 did_notify_ready_to_activate_
= true;
135 host_impl_
->ActivateSyncTree();
137 void NotifyReadyToDraw() override
{}
138 void SetNeedsRedrawOnImplThread() override
{ did_request_redraw_
= true; }
139 void SetNeedsRedrawRectOnImplThread(const gfx::Rect
& damage_rect
) override
{
140 did_request_redraw_
= true;
142 void SetNeedsAnimateOnImplThread() override
{ did_request_animate_
= true; }
143 void SetNeedsPrepareTilesOnImplThread() override
{
144 did_request_prepare_tiles_
= true;
146 void SetNeedsCommitOnImplThread() override
{ did_request_commit_
= true; }
147 void SetVideoNeedsBeginFrames(bool needs_begin_frames
) override
{}
148 void PostAnimationEventsToMainThreadOnImplThread(
149 scoped_ptr
<AnimationEventsVector
> events
) override
{}
150 bool ReduceContentsTextureMemoryOnImplThread(size_t limit_bytes
,
151 int priority_cutoff
) override
{
152 current_limit_bytes_
= limit_bytes
;
153 current_priority_cutoff_value_
= priority_cutoff
;
154 return reduce_memory_result_
;
156 bool IsInsideDraw() override
{ return false; }
157 void RenewTreePriority() override
{}
158 void PostDelayedAnimationTaskOnImplThread(const base::Closure
& task
,
159 base::TimeDelta delay
) override
{
160 animation_task_
= task
;
161 requested_animation_delay_
= delay
;
163 void DidActivateSyncTree() override
{}
164 void DidPrepareTiles() override
{}
165 void DidCompletePageScaleAnimationOnImplThread() override
{
166 did_complete_page_scale_animation_
= true;
168 void OnDrawForOutputSurface() override
{}
170 void set_reduce_memory_result(bool reduce_memory_result
) {
171 reduce_memory_result_
= reduce_memory_result
;
174 virtual bool CreateHostImpl(const LayerTreeSettings
& settings
,
175 scoped_ptr
<OutputSurface
> output_surface
) {
176 host_impl_
= LayerTreeHostImpl::Create(
177 settings
, this, &proxy_
, &stats_instrumentation_
,
178 shared_bitmap_manager_
.get(), gpu_memory_buffer_manager_
.get(),
179 task_graph_runner_
.get(), 0);
180 bool init
= host_impl_
->InitializeRenderer(output_surface
.Pass());
181 host_impl_
->SetViewportSize(gfx::Size(10, 10));
182 // Set the BeginFrameArgs so that methods which use it are able to.
183 host_impl_
->WillBeginImplFrame(
184 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
188 void SetupRootLayerImpl(scoped_ptr
<LayerImpl
> root
) {
189 root
->SetPosition(gfx::PointF());
190 root
->SetBounds(gfx::Size(10, 10));
191 root
->SetContentBounds(gfx::Size(10, 10));
192 root
->SetDrawsContent(true);
193 root
->draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
194 root
->SetHasRenderSurface(true);
195 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
198 static void ExpectClearedScrollDeltasRecursive(LayerImpl
* layer
) {
199 ASSERT_EQ(layer
->ScrollDelta(), gfx::Vector2d());
200 for (size_t i
= 0; i
< layer
->children().size(); ++i
)
201 ExpectClearedScrollDeltasRecursive(layer
->children()[i
]);
204 static void ExpectContains(const ScrollAndScaleSet
& scroll_info
,
206 const gfx::Vector2d
& scroll_delta
) {
207 int times_encountered
= 0;
209 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
210 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
212 EXPECT_VECTOR_EQ(scroll_delta
, scroll_info
.scrolls
[i
].scroll_delta
);
216 ASSERT_EQ(1, times_encountered
);
219 static void ExpectNone(const ScrollAndScaleSet
& scroll_info
, int id
) {
220 int times_encountered
= 0;
222 for (size_t i
= 0; i
< scroll_info
.scrolls
.size(); ++i
) {
223 if (scroll_info
.scrolls
[i
].layer_id
!= id
)
228 ASSERT_EQ(0, times_encountered
);
231 LayerImpl
* CreateScrollAndContentsLayers(LayerTreeImpl
* layer_tree_impl
,
232 const gfx::Size
& content_size
) {
233 // Create both an inner viewport scroll layer and an outer viewport scroll
234 // layer. The MaxScrollOffset of the outer viewport scroll layer will be
235 // 0x0, so the scrolls will be applied directly to the inner viewport.
236 const int kOuterViewportClipLayerId
= 116;
237 const int kOuterViewportScrollLayerId
= 117;
238 const int kContentLayerId
= 118;
239 const int kInnerViewportScrollLayerId
= 2;
240 const int kInnerViewportClipLayerId
= 4;
241 const int kPageScaleLayerId
= 5;
243 scoped_ptr
<LayerImpl
> root
=
244 LayerImpl::Create(layer_tree_impl
, 1);
245 root
->SetBounds(content_size
);
246 root
->SetContentBounds(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
->SetContentBounds(content_size
);
266 inner_scroll
->SetPosition(gfx::PointF());
268 scoped_ptr
<LayerImpl
> outer_clip
=
269 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
270 outer_clip
->SetBounds(content_size
);
271 outer_clip
->SetIsContainerForFixedPositionLayers(true);
273 scoped_ptr
<LayerImpl
> outer_scroll
=
274 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
275 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
276 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
277 outer_scroll
->SetBounds(content_size
);
278 outer_scroll
->SetContentBounds(content_size
);
279 outer_scroll
->SetPosition(gfx::PointF());
281 scoped_ptr
<LayerImpl
> contents
=
282 LayerImpl::Create(layer_tree_impl
, kContentLayerId
);
283 contents
->SetDrawsContent(true);
284 contents
->SetBounds(content_size
);
285 contents
->SetContentBounds(content_size
);
286 contents
->SetPosition(gfx::PointF());
288 outer_scroll
->AddChild(contents
.Pass());
289 outer_clip
->AddChild(outer_scroll
.Pass());
290 inner_scroll
->AddChild(outer_clip
.Pass());
291 page_scale
->AddChild(inner_scroll
.Pass());
292 inner_clip
->AddChild(page_scale
.Pass());
293 root
->AddChild(inner_clip
.Pass());
295 layer_tree_impl
->SetRootLayer(root
.Pass());
296 layer_tree_impl
->SetViewportLayersFromIds(
297 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
298 kOuterViewportScrollLayerId
);
300 layer_tree_impl
->DidBecomeActive();
301 return layer_tree_impl
->InnerViewportScrollLayer();
304 LayerImpl
* SetupScrollAndContentsLayers(const gfx::Size
& content_size
) {
305 LayerImpl
* scroll_layer
= CreateScrollAndContentsLayers(
306 host_impl_
->active_tree(), content_size
);
307 host_impl_
->active_tree()->DidBecomeActive();
311 // TODO(wjmaclean) Add clip-layer pointer to parameters.
312 scoped_ptr
<LayerImpl
> CreateScrollableLayer(int id
,
313 const gfx::Size
& size
,
314 LayerImpl
* clip_layer
) {
316 DCHECK(id
!= clip_layer
->id());
317 scoped_ptr
<LayerImpl
> layer
=
318 LayerImpl::Create(host_impl_
->active_tree(), id
);
319 layer
->SetScrollClipLayer(clip_layer
->id());
320 layer
->SetDrawsContent(true);
321 layer
->SetBounds(size
);
322 layer
->SetContentBounds(size
);
323 clip_layer
->SetBounds(gfx::Size(size
.width() / 2, size
.height() / 2));
328 LayerTreeHostImpl::FrameData frame
;
329 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
330 host_impl_
->DrawLayers(&frame
);
331 host_impl_
->DidDrawAllLayers(frame
);
334 void pinch_zoom_pan_viewport_forces_commit_redraw(float device_scale_factor
);
335 void pinch_zoom_pan_viewport_test(float device_scale_factor
);
336 void pinch_zoom_pan_viewport_and_scroll_test(float device_scale_factor
);
337 void pinch_zoom_pan_viewport_and_scroll_boundary_test(
338 float device_scale_factor
);
340 void CheckNotifyCalledIfCanDrawChanged(bool always_draw
) {
341 // Note: It is not possible to disable the renderer once it has been set,
342 // so we do not need to test that disabling the renderer notifies us
343 // that can_draw changed.
344 EXPECT_FALSE(host_impl_
->CanDraw());
345 on_can_draw_state_changed_called_
= false;
347 // Set up the root layer, which allows us to draw.
348 SetupScrollAndContentsLayers(gfx::Size(100, 100));
349 EXPECT_TRUE(host_impl_
->CanDraw());
350 EXPECT_TRUE(on_can_draw_state_changed_called_
);
351 on_can_draw_state_changed_called_
= false;
353 // Toggle the root layer to make sure it toggles can_draw
354 host_impl_
->active_tree()->SetRootLayer(nullptr);
355 EXPECT_FALSE(host_impl_
->CanDraw());
356 EXPECT_TRUE(on_can_draw_state_changed_called_
);
357 on_can_draw_state_changed_called_
= false;
359 SetupScrollAndContentsLayers(gfx::Size(100, 100));
360 EXPECT_TRUE(host_impl_
->CanDraw());
361 EXPECT_TRUE(on_can_draw_state_changed_called_
);
362 on_can_draw_state_changed_called_
= false;
364 // Toggle the device viewport size to make sure it toggles can_draw.
365 host_impl_
->SetViewportSize(gfx::Size());
367 EXPECT_TRUE(host_impl_
->CanDraw());
369 EXPECT_FALSE(host_impl_
->CanDraw());
371 EXPECT_TRUE(on_can_draw_state_changed_called_
);
372 on_can_draw_state_changed_called_
= false;
374 host_impl_
->SetViewportSize(gfx::Size(100, 100));
375 EXPECT_TRUE(host_impl_
->CanDraw());
376 EXPECT_TRUE(on_can_draw_state_changed_called_
);
377 on_can_draw_state_changed_called_
= false;
379 // Toggle contents textures purged without causing any evictions,
380 // and make sure that it does not change can_draw.
381 set_reduce_memory_result(false);
382 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
383 host_impl_
->memory_allocation_limit_bytes() - 1));
384 EXPECT_TRUE(host_impl_
->CanDraw());
385 EXPECT_FALSE(on_can_draw_state_changed_called_
);
386 on_can_draw_state_changed_called_
= false;
388 // Toggle contents textures purged to make sure it toggles can_draw.
389 set_reduce_memory_result(true);
390 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
391 host_impl_
->memory_allocation_limit_bytes() - 1));
393 EXPECT_TRUE(host_impl_
->CanDraw());
395 EXPECT_FALSE(host_impl_
->CanDraw());
397 EXPECT_TRUE(on_can_draw_state_changed_called_
);
398 on_can_draw_state_changed_called_
= false;
400 host_impl_
->active_tree()->ResetContentsTexturesPurged();
401 EXPECT_TRUE(host_impl_
->CanDraw());
402 EXPECT_TRUE(on_can_draw_state_changed_called_
);
403 on_can_draw_state_changed_called_
= false;
406 void SetupMouseMoveAtWithDeviceScale(float device_scale_factor
);
409 virtual scoped_ptr
<OutputSurface
> CreateOutputSurface() {
410 return FakeOutputSurface::Create3d();
413 void DrawOneFrame() {
414 LayerTreeHostImpl::FrameData frame_data
;
415 host_impl_
->PrepareToDraw(&frame_data
);
416 host_impl_
->DidDrawAllLayers(frame_data
);
420 DebugScopedSetImplThread always_impl_thread_
;
421 DebugScopedSetMainThreadBlocked always_main_thread_blocked_
;
423 scoped_ptr
<TestSharedBitmapManager
> shared_bitmap_manager_
;
424 scoped_ptr
<TestGpuMemoryBufferManager
> gpu_memory_buffer_manager_
;
425 scoped_ptr
<TestTaskGraphRunner
> task_graph_runner_
;
426 scoped_ptr
<LayerTreeHostImpl
> host_impl_
;
427 FakeRenderingStatsInstrumentation stats_instrumentation_
;
428 bool on_can_draw_state_changed_called_
;
429 bool did_notify_ready_to_activate_
;
430 bool did_request_commit_
;
431 bool did_request_redraw_
;
432 bool did_request_animate_
;
433 bool did_request_prepare_tiles_
;
434 bool did_complete_page_scale_animation_
;
435 bool reduce_memory_result_
;
436 base::Closure animation_task_
;
437 base::TimeDelta requested_animation_delay_
;
438 size_t current_limit_bytes_
;
439 int current_priority_cutoff_value_
;
442 TEST_F(LayerTreeHostImplTest
, NotifyIfCanDrawChanged
) {
443 bool always_draw
= false;
444 CheckNotifyCalledIfCanDrawChanged(always_draw
);
447 TEST_F(LayerTreeHostImplTest
, CanDrawIncompleteFrames
) {
448 CreateHostImpl(DefaultSettings(),
449 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
451 bool always_draw
= true;
452 CheckNotifyCalledIfCanDrawChanged(always_draw
);
455 TEST_F(LayerTreeHostImplTest
, ScrollDeltaNoLayers
) {
456 ASSERT_FALSE(host_impl_
->active_tree()->root_layer());
458 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
459 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
462 TEST_F(LayerTreeHostImplTest
, ScrollDeltaTreeButNoChanges
) {
464 scoped_ptr
<LayerImpl
> root
=
465 LayerImpl::Create(host_impl_
->active_tree(), 1);
466 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 2));
467 root
->AddChild(LayerImpl::Create(host_impl_
->active_tree(), 3));
468 root
->children()[1]->AddChild(
469 LayerImpl::Create(host_impl_
->active_tree(), 4));
470 root
->children()[1]->AddChild(
471 LayerImpl::Create(host_impl_
->active_tree(), 5));
472 root
->children()[1]->children()[0]->AddChild(
473 LayerImpl::Create(host_impl_
->active_tree(), 6));
474 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
476 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
478 ExpectClearedScrollDeltasRecursive(root
);
480 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
482 scroll_info
= host_impl_
->ProcessScrollDeltas();
483 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
484 ExpectClearedScrollDeltasRecursive(root
);
486 scroll_info
= host_impl_
->ProcessScrollDeltas();
487 ASSERT_EQ(scroll_info
->scrolls
.size(), 0u);
488 ExpectClearedScrollDeltasRecursive(root
);
491 TEST_F(LayerTreeHostImplTest
, ScrollDeltaRepeatedScrolls
) {
492 gfx::ScrollOffset
scroll_offset(20, 30);
493 gfx::Vector2d
scroll_delta(11, -15);
495 scoped_ptr
<LayerImpl
> root_clip
=
496 LayerImpl::Create(host_impl_
->active_tree(), 2);
497 scoped_ptr
<LayerImpl
> root
=
498 LayerImpl::Create(host_impl_
->active_tree(), 1);
499 root_clip
->SetBounds(gfx::Size(10, 10));
500 LayerImpl
* root_layer
= root
.get();
501 root_clip
->AddChild(root
.Pass());
502 root_layer
->SetBounds(gfx::Size(110, 110));
503 root_layer
->SetScrollClipLayer(root_clip
->id());
504 root_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
505 root_layer
->ScrollBy(scroll_delta
);
506 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
508 LayerImpl
* root
= host_impl_
->active_tree()->root_layer()->children()[0];
510 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
512 scroll_info
= host_impl_
->ProcessScrollDeltas();
513 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
514 ExpectContains(*scroll_info
, root
->id(), scroll_delta
);
516 gfx::Vector2d
scroll_delta2(-5, 27);
517 root
->ScrollBy(scroll_delta2
);
518 scroll_info
= host_impl_
->ProcessScrollDeltas();
519 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
520 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
522 root
->ScrollBy(gfx::Vector2d());
523 scroll_info
= host_impl_
->ProcessScrollDeltas();
524 ExpectContains(*scroll_info
, root
->id(), scroll_delta
+ scroll_delta2
);
527 TEST_F(LayerTreeHostImplTest
, ScrollRootCallsCommitAndRedraw
) {
528 SetupScrollAndContentsLayers(gfx::Size(100, 100));
529 host_impl_
->SetViewportSize(gfx::Size(50, 50));
532 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
533 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
534 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
535 InputHandler::WHEEL
));
536 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
537 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(0, 10),
538 InputHandler::WHEEL
));
539 host_impl_
->ScrollEnd();
540 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
541 InputHandler::WHEEL
));
542 EXPECT_TRUE(did_request_redraw_
);
543 EXPECT_TRUE(did_request_commit_
);
546 TEST_F(LayerTreeHostImplTest
, ScrollActiveOnlyAfterScrollMovement
) {
547 SetupScrollAndContentsLayers(gfx::Size(100, 100));
548 host_impl_
->SetViewportSize(gfx::Size(50, 50));
551 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
552 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
553 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
554 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
555 EXPECT_TRUE(host_impl_
->IsActivelyScrolling());
556 host_impl_
->ScrollEnd();
557 EXPECT_FALSE(host_impl_
->IsActivelyScrolling());
560 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRootLayer
) {
561 // We should not crash when trying to scroll an empty layer tree.
562 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
563 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
566 TEST_F(LayerTreeHostImplTest
, ScrollWithoutRenderer
) {
567 scoped_ptr
<TestWebGraphicsContext3D
> context_owned
=
568 TestWebGraphicsContext3D::Create();
569 context_owned
->set_context_lost(true);
571 // Initialization will fail.
572 EXPECT_FALSE(CreateHostImpl(
573 DefaultSettings(), FakeOutputSurface::Create3d(context_owned
.Pass())));
575 SetupScrollAndContentsLayers(gfx::Size(100, 100));
577 // We should not crash when trying to scroll after the renderer initialization
579 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
580 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
583 TEST_F(LayerTreeHostImplTest
, ReplaceTreeWhileScrolling
) {
584 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
585 host_impl_
->SetViewportSize(gfx::Size(50, 50));
588 // We should not crash if the tree is replaced while we are scrolling.
589 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
590 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
591 host_impl_
->active_tree()->DetachLayerTree();
593 scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
595 // We should still be scrolling, because the scrolled layer also exists in the
597 gfx::Vector2d
scroll_delta(0, 10);
598 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
599 host_impl_
->ScrollEnd();
600 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
601 ExpectContains(*scroll_info
, scroll_layer
->id(), scroll_delta
);
604 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnWheelEventHandlers
) {
605 SetupScrollAndContentsLayers(gfx::Size(100, 100));
606 host_impl_
->SetViewportSize(gfx::Size(50, 50));
608 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
610 // With registered event handlers, wheel scrolls don't necessarily
611 // have to go to the main thread.
612 root
->SetHaveWheelEventHandlers(true);
613 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
614 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
615 host_impl_
->ScrollEnd();
617 // But typically the scroll-blocks-on mode will require them to.
618 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
619 SCROLL_BLOCKS_ON_START_TOUCH
);
620 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
621 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
623 // But gesture scrolls can still be handled.
624 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
625 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
626 host_impl_
->ScrollEnd();
628 // And if the handlers go away, wheel scrolls can again be processed
629 // on impl (despite the scroll-blocks-on mode).
630 root
->SetHaveWheelEventHandlers(false);
631 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
632 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
633 host_impl_
->ScrollEnd();
636 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnTouchEventHandlers
) {
637 LayerImpl
* scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
638 host_impl_
->SetViewportSize(gfx::Size(50, 50));
640 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
642 LayerImpl
* child
= 0;
644 scoped_ptr
<LayerImpl
> child_layer
=
645 LayerImpl::Create(host_impl_
->active_tree(), 6);
646 child
= child_layer
.get();
647 child_layer
->SetDrawsContent(true);
648 child_layer
->SetPosition(gfx::PointF(0, 20));
649 child_layer
->SetBounds(gfx::Size(50, 50));
650 child_layer
->SetContentBounds(gfx::Size(50, 50));
651 scroll
->AddChild(child_layer
.Pass());
654 // Touch handler regions determine whether touch events block scroll.
655 root
->SetTouchEventHandlerRegion(gfx::Rect(0, 0, 100, 100));
656 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
657 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
|
658 SCROLL_BLOCKS_ON_WHEEL_EVENT
);
659 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 10)));
661 // But they don't influence the actual handling of the scroll gestures.
662 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
663 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
664 host_impl_
->ScrollEnd();
666 // It's the union of scroll-blocks-on mode bits across all layers in the
667 // scroll paret chain that matters.
668 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
669 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_NONE
);
670 EXPECT_FALSE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
671 child
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_START_TOUCH
);
672 EXPECT_TRUE(host_impl_
->DoTouchEventsBlockScrollAt(gfx::Point(10, 30)));
675 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnScrollEventHandlers
) {
676 SetupScrollAndContentsLayers(gfx::Size(100, 100));
677 host_impl_
->SetViewportSize(gfx::Size(50, 50));
679 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
681 // With registered scroll handlers, scrolls don't generally have to go
682 // to the main thread.
683 root
->SetHaveScrollEventHandlers(true);
684 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
685 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
686 host_impl_
->ScrollEnd();
688 // Even the default scroll blocks on mode doesn't require this.
689 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
|
690 SCROLL_BLOCKS_ON_START_TOUCH
);
691 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
692 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
693 host_impl_
->ScrollEnd();
695 // But the page can opt in to blocking on scroll event handlers.
696 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
697 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
698 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
700 // GESTURE and WHEEL scrolls behave identically in this regard.
701 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
702 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
704 // And if the handlers go away, scrolls can again be processed on impl
705 // (despite the scroll-blocks-on mode).
706 root
->SetHaveScrollEventHandlers(false);
707 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
708 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
709 host_impl_
->ScrollEnd();
712 TEST_F(LayerTreeHostImplTest
, ScrollBlocksOnLayerTopology
) {
713 host_impl_
->SetViewportSize(gfx::Size(50, 50));
715 // Create a normal scrollable root layer
716 LayerImpl
* root_scroll
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
717 LayerImpl
* root_child
= root_scroll
->children()[0];
718 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
721 // Create two child scrollable layers
722 LayerImpl
* child1
= 0;
724 scoped_ptr
<LayerImpl
> scrollable_child_clip_1
=
725 LayerImpl::Create(host_impl_
->active_tree(), 6);
726 scoped_ptr
<LayerImpl
> scrollable_child_1
= CreateScrollableLayer(
727 7, gfx::Size(10, 10), scrollable_child_clip_1
.get());
728 child1
= scrollable_child_1
.get();
729 scrollable_child_1
->SetPosition(gfx::Point(5, 5));
730 scrollable_child_1
->SetHaveWheelEventHandlers(true);
731 scrollable_child_1
->SetHaveScrollEventHandlers(true);
732 scrollable_child_clip_1
->AddChild(scrollable_child_1
.Pass());
733 root_child
->AddChild(scrollable_child_clip_1
.Pass());
736 LayerImpl
* child2
= 0;
738 scoped_ptr
<LayerImpl
> scrollable_child_clip_2
=
739 LayerImpl::Create(host_impl_
->active_tree(), 8);
740 scoped_ptr
<LayerImpl
> scrollable_child_2
= CreateScrollableLayer(
741 9, gfx::Size(10, 10), scrollable_child_clip_2
.get());
742 child2
= scrollable_child_2
.get();
743 scrollable_child_2
->SetPosition(gfx::Point(5, 20));
744 scrollable_child_2
->SetHaveWheelEventHandlers(true);
745 scrollable_child_2
->SetHaveScrollEventHandlers(true);
746 scrollable_child_clip_2
->AddChild(scrollable_child_2
.Pass());
747 root_child
->AddChild(scrollable_child_clip_2
.Pass());
750 // Scroll-blocks-on on a layer affects scrolls that hit that layer.
751 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
752 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
753 host_impl_
->ScrollEnd();
754 child1
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
755 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
756 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
));
758 // But not those that hit only other layers.
759 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
760 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
761 host_impl_
->ScrollEnd();
763 // It's the union of bits set across the scroll ancestor chain that matters.
764 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
765 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
766 host_impl_
->ScrollEnd();
767 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
768 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
769 host_impl_
->ScrollEnd();
770 root
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_WHEEL_EVENT
);
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_ON_MAIN_THREAD
,
775 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
776 child2
->SetScrollBlocksOn(SCROLL_BLOCKS_ON_SCROLL_EVENT
);
777 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
778 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::WHEEL
));
779 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
780 host_impl_
->ScrollBegin(gfx::Point(10, 25), InputHandler::GESTURE
));
783 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchscreen
) {
784 SetupScrollAndContentsLayers(gfx::Size(100, 100));
785 host_impl_
->SetViewportSize(gfx::Size(50, 50));
788 // Ignore the fling since no layer is being scrolled
789 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
791 // Start scrolling a layer
792 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
793 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
795 // Now the fling should go ahead since we've started scrolling a layer
796 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
799 TEST_F(LayerTreeHostImplTest
, FlingOnlyWhenScrollingTouchpad
) {
800 SetupScrollAndContentsLayers(gfx::Size(100, 100));
801 host_impl_
->SetViewportSize(gfx::Size(50, 50));
804 // Ignore the fling since no layer is being scrolled
805 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
807 // Start scrolling a layer
808 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
809 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
811 // Now the fling should go ahead since we've started scrolling a layer
812 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
815 TEST_F(LayerTreeHostImplTest
, NoFlingWhenScrollingOnMain
) {
816 SetupScrollAndContentsLayers(gfx::Size(100, 100));
817 host_impl_
->SetViewportSize(gfx::Size(50, 50));
819 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
821 root
->SetShouldScrollOnMainThread(true);
823 // Start scrolling a layer
824 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
825 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
827 // The fling should be ignored since there's no layer being scrolled impl-side
828 EXPECT_EQ(InputHandler::SCROLL_IGNORED
, host_impl_
->FlingScrollBegin());
831 TEST_F(LayerTreeHostImplTest
, ShouldScrollOnMainThread
) {
832 SetupScrollAndContentsLayers(gfx::Size(100, 100));
833 host_impl_
->SetViewportSize(gfx::Size(50, 50));
835 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
837 root
->SetShouldScrollOnMainThread(true);
839 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
840 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
841 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
842 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
845 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionBasic
) {
846 SetupScrollAndContentsLayers(gfx::Size(200, 200));
847 host_impl_
->SetViewportSize(gfx::Size(100, 100));
849 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
850 root
->SetContentsScale(2.f
, 2.f
);
851 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
855 // All scroll types inside the non-fast scrollable region should fail.
856 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
857 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::WHEEL
));
858 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
859 InputHandler::WHEEL
));
860 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
861 host_impl_
->ScrollBegin(gfx::Point(25, 25), InputHandler::GESTURE
));
862 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
863 InputHandler::GESTURE
));
865 // All scroll types outside this region should succeed.
866 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
867 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::WHEEL
));
868 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
869 InputHandler::GESTURE
));
870 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
871 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(25, 25),
872 InputHandler::GESTURE
));
873 host_impl_
->ScrollEnd();
874 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
875 InputHandler::GESTURE
));
876 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
877 host_impl_
->ScrollBegin(gfx::Point(75, 75), InputHandler::GESTURE
));
878 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
879 InputHandler::GESTURE
));
880 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
881 host_impl_
->ScrollEnd();
882 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(75, 75),
883 InputHandler::GESTURE
));
886 TEST_F(LayerTreeHostImplTest
, NonFastScrollableRegionWithOffset
) {
887 SetupScrollAndContentsLayers(gfx::Size(200, 200));
888 host_impl_
->SetViewportSize(gfx::Size(100, 100));
890 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
891 root
->SetContentsScale(2.f
, 2.f
);
892 root
->SetNonFastScrollableRegion(gfx::Rect(0, 0, 50, 50));
893 root
->SetPosition(gfx::PointF(-25.f
, 0.f
));
897 // This point would fall into the non-fast scrollable region except that we've
898 // moved the layer down by 25 pixels.
899 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
900 host_impl_
->ScrollBegin(gfx::Point(40, 10), InputHandler::WHEEL
));
901 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(40, 10),
902 InputHandler::WHEEL
));
903 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 1));
904 host_impl_
->ScrollEnd();
906 // This point is still inside the non-fast region.
907 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
908 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::WHEEL
));
911 TEST_F(LayerTreeHostImplTest
, ScrollHandlerNotPresent
) {
912 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
913 EXPECT_FALSE(scroll_layer
->have_scroll_event_handlers());
914 host_impl_
->SetViewportSize(gfx::Size(50, 50));
917 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
918 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
919 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
920 host_impl_
->ScrollEnd();
921 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
924 TEST_F(LayerTreeHostImplTest
, ScrollHandlerPresent
) {
925 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
926 scroll_layer
->SetHaveScrollEventHandlers(true);
927 host_impl_
->SetViewportSize(gfx::Size(50, 50));
930 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
931 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
932 EXPECT_TRUE(host_impl_
->scroll_affects_scroll_handler());
933 host_impl_
->ScrollEnd();
934 EXPECT_FALSE(host_impl_
->scroll_affects_scroll_handler());
937 TEST_F(LayerTreeHostImplTest
, ScrollByReturnsCorrectValue
) {
938 SetupScrollAndContentsLayers(gfx::Size(200, 200));
939 host_impl_
->SetViewportSize(gfx::Size(100, 100));
943 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
944 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
946 // Trying to scroll to the left/top will not succeed.
948 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
950 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
952 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
954 // Scrolling to the right/bottom will succeed.
956 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll
);
958 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
960 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll
);
962 // Scrolling to left/top will now succeed.
964 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
966 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll
);
968 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll
);
970 // Scrolling diagonally against an edge will succeed.
972 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll
);
974 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll
);
976 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll
);
978 // Trying to scroll more than the available space will also succeed.
980 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll
);
983 TEST_F(LayerTreeHostImplTest
, ScrollVerticallyByPageReturnsCorrectValue
) {
984 SetupScrollAndContentsLayers(gfx::Size(200, 2000));
985 host_impl_
->SetViewportSize(gfx::Size(100, 1000));
989 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
990 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
992 // Trying to scroll without a vertical scrollbar will fail.
993 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
994 gfx::Point(), SCROLL_FORWARD
));
995 EXPECT_FALSE(host_impl_
->ScrollVerticallyByPage(
996 gfx::Point(), SCROLL_BACKWARD
));
998 scoped_ptr
<PaintedScrollbarLayerImpl
> vertical_scrollbar(
999 PaintedScrollbarLayerImpl::Create(
1000 host_impl_
->active_tree(),
1003 vertical_scrollbar
->SetBounds(gfx::Size(15, 1000));
1004 host_impl_
->InnerViewportScrollLayer()->AddScrollbar(
1005 vertical_scrollbar
.get());
1007 // Trying to scroll with a vertical scrollbar will succeed.
1008 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1009 gfx::Point(), SCROLL_FORWARD
));
1010 EXPECT_FLOAT_EQ(875.f
,
1011 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
1012 EXPECT_TRUE(host_impl_
->ScrollVerticallyByPage(
1013 gfx::Point(), SCROLL_BACKWARD
));
1016 TEST_F(LayerTreeHostImplTest
, ScrollWithUserUnscrollableLayers
) {
1017 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(200, 200));
1018 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1020 gfx::Size
overflow_size(400, 400);
1021 ASSERT_EQ(1u, scroll_layer
->children().size());
1022 LayerImpl
* overflow
= scroll_layer
->children()[0];
1023 overflow
->SetBounds(overflow_size
);
1024 overflow
->SetContentBounds(overflow_size
);
1025 overflow
->SetScrollClipLayer(scroll_layer
->parent()->id());
1026 overflow
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1027 overflow
->SetPosition(gfx::PointF());
1030 gfx::Point
scroll_position(10, 10);
1032 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1033 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1034 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1035 EXPECT_VECTOR_EQ(gfx::Vector2dF(), overflow
->CurrentScrollOffset());
1037 gfx::Vector2dF
scroll_delta(10, 10);
1038 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1039 host_impl_
->ScrollEnd();
1040 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1041 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1043 overflow
->set_user_scrollable_horizontal(false);
1045 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1046 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1047 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
1048 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 10), overflow
->CurrentScrollOffset());
1050 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1051 host_impl_
->ScrollEnd();
1052 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1053 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1055 overflow
->set_user_scrollable_vertical(false);
1057 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1058 host_impl_
->ScrollBegin(scroll_position
, InputHandler::WHEEL
));
1059 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 0), scroll_layer
->CurrentScrollOffset());
1060 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1062 host_impl_
->ScrollBy(scroll_position
, scroll_delta
);
1063 host_impl_
->ScrollEnd();
1064 EXPECT_VECTOR_EQ(gfx::Vector2dF(20, 10), scroll_layer
->CurrentScrollOffset());
1065 EXPECT_VECTOR_EQ(gfx::Vector2dF(10, 20), overflow
->CurrentScrollOffset());
1068 TEST_F(LayerTreeHostImplTest
, ImplPinchZoom
) {
1069 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
1070 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1073 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
1074 LayerImpl
* container_layer
= scroll_layer
->scroll_clip_layer();
1075 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1077 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1078 float page_scale_factor
= 1.f
;
1080 // The impl-based pinch zoom should adjust the max scroll position.
1082 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1083 page_scale_factor
, min_page_scale
, max_page_scale
);
1084 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1085 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1087 float page_scale_delta
= 2.f
;
1089 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1090 host_impl_
->PinchGestureBegin();
1091 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1092 host_impl_
->PinchGestureEnd();
1093 host_impl_
->ScrollEnd();
1094 EXPECT_FALSE(did_request_animate_
);
1095 EXPECT_TRUE(did_request_redraw_
);
1096 EXPECT_TRUE(did_request_commit_
);
1097 EXPECT_EQ(gfx::Size(50, 50), container_layer
->bounds());
1099 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1100 host_impl_
->ProcessScrollDeltas();
1101 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1103 EXPECT_EQ(gfx::ScrollOffset(75.0, 75.0).ToString(),
1104 scroll_layer
->MaxScrollOffset().ToString());
1107 // Scrolling after a pinch gesture should always be in local space. The
1108 // scroll deltas have the page scale factor applied.
1110 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1111 page_scale_factor
, min_page_scale
, max_page_scale
);
1112 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1113 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1115 float page_scale_delta
= 2.f
;
1116 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1117 host_impl_
->PinchGestureBegin();
1118 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1119 host_impl_
->PinchGestureEnd();
1120 host_impl_
->ScrollEnd();
1122 gfx::Vector2d
scroll_delta(0, 10);
1123 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1124 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
1125 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
1126 host_impl_
->ScrollEnd();
1128 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1129 host_impl_
->ProcessScrollDeltas();
1130 ExpectContains(*scroll_info
.get(), scroll_layer
->id(),
1131 gfx::Vector2d(0, scroll_delta
.y() / page_scale_delta
));
1135 TEST_F(LayerTreeHostImplTest
, ImplPinchZoomWheelBubbleBetweenViewports
) {
1136 LayerImpl
* inner_scroll_layer
=
1137 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1139 // Adjust the content layer to be larger than the outer viewport container so
1140 // that we get scrolling in both viewports.
1141 LayerImpl
* content_layer
=
1142 host_impl_
->OuterViewportScrollLayer()->children().back();
1143 LayerImpl
* outer_scroll_layer
= host_impl_
->OuterViewportScrollLayer();
1144 LayerImpl
* inner_clip_layer
=
1145 host_impl_
->InnerViewportScrollLayer()->parent()->parent();
1146 inner_clip_layer
->SetBounds(gfx::Size(100, 100));
1147 inner_clip_layer
->SetContentBounds(gfx::Size(100, 100));
1148 outer_scroll_layer
->SetBounds(gfx::Size(200, 200));
1149 outer_scroll_layer
->SetContentBounds(gfx::Size(200, 200));
1150 content_layer
->SetBounds(gfx::Size(200, 200));
1151 content_layer
->SetContentBounds(gfx::Size(200, 200));
1153 host_impl_
->SetViewportSize(gfx::Size(100, 100));
1157 // Zoom into the page by a 2X factor
1158 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
1159 float page_scale_factor
= 2.f
;
1160 host_impl_
->active_tree()->PushPageScaleFromMainThread(
1161 page_scale_factor
, min_page_scale
, max_page_scale
);
1162 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
1164 // Scroll by a small amount, there should be no bubbling up to the inner
1166 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1167 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(10.f
, 20.f
));
1168 host_impl_
->ScrollEnd();
1171 gfx::Vector2dF(5, 10),
1172 outer_scroll_layer
->CurrentScrollOffset());
1175 inner_scroll_layer
->CurrentScrollOffset());
1177 // Scroll by the outer viewport's max scroll extent, there the remainder
1178 // should bubble up to the inner viewport.
1179 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1180 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(200.f
, 200.f
));
1181 host_impl_
->ScrollEnd();
1184 gfx::Vector2dF(100, 100),
1185 outer_scroll_layer
->CurrentScrollOffset());
1187 gfx::Vector2dF(5, 10),
1188 inner_scroll_layer
->CurrentScrollOffset());
1190 // Scroll by the inner viewport's max scroll extent, it should all go to the
1192 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
);
1193 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2dF(90.f
, 80.f
));
1194 host_impl_
->ScrollEnd();
1197 gfx::Vector2dF(100, 100),
1198 outer_scroll_layer
->CurrentScrollOffset());
1200 gfx::Vector2dF(50, 50),
1201 inner_scroll_layer
->CurrentScrollOffset());
1204 TEST_F(LayerTreeHostImplTest
, ScrollWithSwapPromises
) {
1205 ui::LatencyInfo latency_info
;
1206 latency_info
.trace_id
= 1234;
1207 scoped_ptr
<SwapPromise
> swap_promise(
1208 new LatencyInfoSwapPromise(latency_info
));
1210 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1211 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1212 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
1213 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1214 host_impl_
->QueueSwapPromiseForMainThreadScrollUpdate(swap_promise
.Pass());
1215 host_impl_
->ScrollEnd();
1217 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
1218 EXPECT_EQ(1u, scroll_info
->swap_promises
.size());
1219 EXPECT_EQ(latency_info
.trace_id
, scroll_info
->swap_promises
[0]->TraceId());
1222 TEST_F(LayerTreeHostImplTest
, PinchGesture
) {
1223 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1224 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1227 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1228 DCHECK(scroll_layer
);
1230 float min_page_scale
= 1.f
;
1231 float max_page_scale
= 4.f
;
1233 // Basic pinch zoom in gesture
1235 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1237 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1239 float page_scale_delta
= 2.f
;
1240 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1241 host_impl_
->PinchGestureBegin();
1242 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1243 host_impl_
->PinchGestureEnd();
1244 host_impl_
->ScrollEnd();
1245 EXPECT_FALSE(did_request_animate_
);
1246 EXPECT_TRUE(did_request_redraw_
);
1247 EXPECT_TRUE(did_request_commit_
);
1249 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1250 host_impl_
->ProcessScrollDeltas();
1251 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1256 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1258 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1259 float page_scale_delta
= 10.f
;
1261 host_impl_
->ScrollBegin(gfx::Point(50, 50), InputHandler::GESTURE
);
1262 host_impl_
->PinchGestureBegin();
1263 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(50, 50));
1264 host_impl_
->PinchGestureEnd();
1265 host_impl_
->ScrollEnd();
1267 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1268 host_impl_
->ProcessScrollDeltas();
1269 EXPECT_EQ(scroll_info
->page_scale_delta
, max_page_scale
);
1272 // Zoom-out clamping
1274 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1276 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1277 scroll_layer
->PullDeltaForMainThread();
1278 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1280 float page_scale_delta
= 0.1f
;
1281 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1282 host_impl_
->PinchGestureBegin();
1283 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
1284 host_impl_
->PinchGestureEnd();
1285 host_impl_
->ScrollEnd();
1287 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1288 host_impl_
->ProcessScrollDeltas();
1289 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1291 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1294 // Two-finger panning should not happen based on pinch events only
1296 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1298 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1299 scroll_layer
->PullDeltaForMainThread();
1300 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1302 float page_scale_delta
= 1.f
;
1303 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1304 host_impl_
->PinchGestureBegin();
1305 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1306 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1307 host_impl_
->PinchGestureEnd();
1308 host_impl_
->ScrollEnd();
1310 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1311 host_impl_
->ProcessScrollDeltas();
1312 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1313 EXPECT_TRUE(scroll_info
->scrolls
.empty());
1316 // Two-finger panning should work with interleaved scroll events
1318 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1320 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1321 scroll_layer
->PullDeltaForMainThread();
1322 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(20, 20));
1324 float page_scale_delta
= 1.f
;
1325 host_impl_
->ScrollBegin(gfx::Point(10, 10), InputHandler::GESTURE
);
1326 host_impl_
->PinchGestureBegin();
1327 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(10, 10));
1328 host_impl_
->ScrollBy(gfx::Point(10, 10), gfx::Vector2d(-10, -10));
1329 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point(20, 20));
1330 host_impl_
->PinchGestureEnd();
1331 host_impl_
->ScrollEnd();
1333 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1334 host_impl_
->ProcessScrollDeltas();
1335 EXPECT_EQ(scroll_info
->page_scale_delta
, page_scale_delta
);
1336 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-10, -10));
1339 // Two-finger panning should work when starting fully zoomed out.
1341 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.5f
, 0.5f
, 4.f
);
1342 scroll_layer
->SetScrollDelta(gfx::Vector2d());
1343 scroll_layer
->PullDeltaForMainThread();
1344 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 0));
1346 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::GESTURE
);
1347 host_impl_
->PinchGestureBegin();
1348 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point(0, 0));
1349 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(0, 0));
1350 host_impl_
->ScrollBy(gfx::Point(0, 0), gfx::Vector2d(10, 10));
1351 host_impl_
->PinchGestureUpdate(1.f
, gfx::Point(10, 10));
1352 host_impl_
->PinchGestureEnd();
1353 host_impl_
->ScrollEnd();
1355 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1356 host_impl_
->ProcessScrollDeltas();
1357 EXPECT_EQ(scroll_info
->page_scale_delta
, 2.f
);
1358 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(20, 20));
1362 TEST_F(LayerTreeHostImplTest
, PageScaleAnimation
) {
1363 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1364 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1367 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1368 DCHECK(scroll_layer
);
1370 float min_page_scale
= 0.5f
;
1371 float max_page_scale
= 4.f
;
1372 base::TimeTicks start_time
= base::TimeTicks() +
1373 base::TimeDelta::FromSeconds(1);
1374 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1375 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1376 base::TimeTicks end_time
= start_time
+ duration
;
1378 // Non-anchor zoom-in
1380 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1382 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1384 did_request_redraw_
= false;
1385 did_request_animate_
= false;
1386 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1387 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1392 host_impl_
->ActivateSyncTree();
1393 EXPECT_FALSE(did_request_redraw_
);
1394 EXPECT_TRUE(did_request_animate_
);
1396 did_request_redraw_
= false;
1397 did_request_animate_
= false;
1398 host_impl_
->Animate(start_time
);
1399 EXPECT_TRUE(did_request_redraw_
);
1400 EXPECT_TRUE(did_request_animate_
);
1402 did_request_redraw_
= false;
1403 did_request_animate_
= false;
1404 host_impl_
->Animate(halfway_through_animation
);
1405 EXPECT_TRUE(did_request_redraw_
);
1406 EXPECT_TRUE(did_request_animate_
);
1408 did_request_redraw_
= false;
1409 did_request_animate_
= false;
1410 did_request_commit_
= false;
1411 host_impl_
->Animate(end_time
);
1412 EXPECT_TRUE(did_request_commit_
);
1413 EXPECT_FALSE(did_request_animate_
);
1415 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1416 host_impl_
->ProcessScrollDeltas();
1417 EXPECT_EQ(scroll_info
->page_scale_delta
, 2);
1418 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1423 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1425 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1427 did_request_redraw_
= false;
1428 did_request_animate_
= false;
1429 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1430 scoped_ptr
<PendingPageScaleAnimation
> (new PendingPageScaleAnimation(
1431 gfx::Vector2d(25, 25),
1435 host_impl_
->ActivateSyncTree();
1436 EXPECT_FALSE(did_request_redraw_
);
1437 EXPECT_TRUE(did_request_animate_
);
1439 did_request_redraw_
= false;
1440 did_request_animate_
= false;
1441 host_impl_
->Animate(start_time
);
1442 EXPECT_TRUE(did_request_redraw_
);
1443 EXPECT_TRUE(did_request_animate_
);
1445 did_request_redraw_
= false;
1446 did_request_commit_
= false;
1447 did_request_animate_
= false;
1448 host_impl_
->Animate(end_time
);
1449 EXPECT_TRUE(did_request_redraw_
);
1450 EXPECT_FALSE(did_request_animate_
);
1451 EXPECT_TRUE(did_request_commit_
);
1453 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1454 host_impl_
->ProcessScrollDeltas();
1455 EXPECT_EQ(scroll_info
->page_scale_delta
, min_page_scale
);
1456 // Pushed to (0,0) via clamping against contents layer size.
1457 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1461 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationNoOp
) {
1462 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1463 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1466 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1467 DCHECK(scroll_layer
);
1469 float min_page_scale
= 0.5f
;
1470 float max_page_scale
= 4.f
;
1471 base::TimeTicks start_time
= base::TimeTicks() +
1472 base::TimeDelta::FromSeconds(1);
1473 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1474 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1475 base::TimeTicks end_time
= start_time
+ duration
;
1477 // Anchor zoom with unchanged page scale should not change scroll or scale.
1479 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1481 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1483 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1484 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1489 host_impl_
->ActivateSyncTree();
1490 host_impl_
->Animate(start_time
);
1491 host_impl_
->Animate(halfway_through_animation
);
1492 EXPECT_TRUE(did_request_redraw_
);
1493 host_impl_
->Animate(end_time
);
1494 EXPECT_TRUE(did_request_commit_
);
1496 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1497 host_impl_
->ProcessScrollDeltas();
1498 EXPECT_EQ(scroll_info
->page_scale_delta
, 1);
1499 ExpectNone(*scroll_info
, scroll_layer
->id());
1503 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationTransferedOnSyncTreeActivate
) {
1504 host_impl_
->CreatePendingTree();
1505 CreateScrollAndContentsLayers(
1506 host_impl_
->pending_tree(),
1507 gfx::Size(100, 100));
1508 host_impl_
->ActivateSyncTree();
1511 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1512 DCHECK(scroll_layer
);
1514 float min_page_scale
= 0.5f
;
1515 float max_page_scale
= 4.f
;
1516 host_impl_
->sync_tree()->PushPageScaleFromMainThread(1.f
, min_page_scale
,
1518 host_impl_
->ActivateSyncTree();
1520 base::TimeTicks start_time
= base::TimeTicks() +
1521 base::TimeDelta::FromSeconds(1);
1522 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1523 base::TimeTicks third_through_animation
= start_time
+ duration
/ 3;
1524 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1525 base::TimeTicks end_time
= start_time
+ duration
;
1526 float target_scale
= 2.f
;
1528 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1530 // Make sure TakePageScaleAnimation works properly.
1532 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1533 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1538 scoped_ptr
<PendingPageScaleAnimation
> psa
=
1539 host_impl_
->sync_tree()->TakePendingPageScaleAnimation();
1540 EXPECT_EQ(target_scale
, psa
->scale
);
1541 EXPECT_EQ(duration
, psa
->duration
);
1542 EXPECT_EQ(nullptr, host_impl_
->sync_tree()->TakePendingPageScaleAnimation());
1544 // Recreate the PSA. Nothing should happen here since the tree containing the
1545 // PSA hasn't been activated yet.
1546 did_request_redraw_
= false;
1547 did_request_animate_
= false;
1548 host_impl_
->sync_tree()->SetPendingPageScaleAnimation(
1549 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1554 host_impl_
->Animate(halfway_through_animation
);
1555 EXPECT_FALSE(did_request_animate_
);
1556 EXPECT_FALSE(did_request_redraw_
);
1558 // Activate the sync tree. This should cause the animation to become enabled.
1559 // It should also clear the pointer on the sync tree.
1560 host_impl_
->ActivateSyncTree();
1562 host_impl_
->sync_tree()->TakePendingPageScaleAnimation().get());
1563 EXPECT_FALSE(did_request_redraw_
);
1564 EXPECT_TRUE(did_request_animate_
);
1566 // From here on, make sure the animation runs as normal.
1567 did_request_redraw_
= false;
1568 did_request_animate_
= false;
1569 host_impl_
->Animate(start_time
);
1570 EXPECT_TRUE(did_request_redraw_
);
1571 EXPECT_TRUE(did_request_animate_
);
1573 did_request_redraw_
= false;
1574 did_request_animate_
= false;
1575 host_impl_
->Animate(third_through_animation
);
1576 EXPECT_TRUE(did_request_redraw_
);
1577 EXPECT_TRUE(did_request_animate_
);
1579 // Another activation shouldn't have any effect on the animation.
1580 host_impl_
->ActivateSyncTree();
1582 did_request_redraw_
= false;
1583 did_request_animate_
= false;
1584 host_impl_
->Animate(halfway_through_animation
);
1585 EXPECT_TRUE(did_request_redraw_
);
1586 EXPECT_TRUE(did_request_animate_
);
1588 did_request_redraw_
= false;
1589 did_request_animate_
= false;
1590 did_request_commit_
= false;
1591 host_impl_
->Animate(end_time
);
1592 EXPECT_TRUE(did_request_commit_
);
1593 EXPECT_FALSE(did_request_animate_
);
1595 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
1596 host_impl_
->ProcessScrollDeltas();
1597 EXPECT_EQ(scroll_info
->page_scale_delta
, target_scale
);
1598 ExpectContains(*scroll_info
, scroll_layer
->id(), gfx::Vector2d(-50, -50));
1601 TEST_F(LayerTreeHostImplTest
, PageScaleAnimationCompletedNotification
) {
1602 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1603 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1606 LayerImpl
* scroll_layer
= host_impl_
->InnerViewportScrollLayer();
1607 DCHECK(scroll_layer
);
1609 base::TimeTicks start_time
=
1610 base::TimeTicks() + base::TimeDelta::FromSeconds(1);
1611 base::TimeDelta duration
= base::TimeDelta::FromMilliseconds(100);
1612 base::TimeTicks halfway_through_animation
= start_time
+ duration
/ 2;
1613 base::TimeTicks end_time
= start_time
+ duration
;
1615 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1616 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(50, 50));
1618 did_complete_page_scale_animation_
= false;
1619 host_impl_
->active_tree()->SetPendingPageScaleAnimation(
1620 scoped_ptr
<PendingPageScaleAnimation
>(new PendingPageScaleAnimation(
1621 gfx::Vector2d(), false, 2.f
, duration
)));
1622 host_impl_
->ActivateSyncTree();
1623 host_impl_
->Animate(start_time
);
1624 EXPECT_FALSE(did_complete_page_scale_animation_
);
1626 host_impl_
->Animate(halfway_through_animation
);
1627 EXPECT_FALSE(did_complete_page_scale_animation_
);
1629 host_impl_
->Animate(end_time
);
1630 EXPECT_TRUE(did_complete_page_scale_animation_
);
1633 class LayerTreeHostImplOverridePhysicalTime
: public LayerTreeHostImpl
{
1635 LayerTreeHostImplOverridePhysicalTime(
1636 const LayerTreeSettings
& settings
,
1637 LayerTreeHostImplClient
* client
,
1639 SharedBitmapManager
* manager
,
1640 RenderingStatsInstrumentation
* rendering_stats_instrumentation
)
1641 : LayerTreeHostImpl(settings
,
1644 rendering_stats_instrumentation
,
1650 BeginFrameArgs
CurrentBeginFrameArgs() const override
{
1651 return CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
,
1652 fake_current_physical_time_
);
1655 void SetCurrentPhysicalTimeTicksForTest(base::TimeTicks fake_now
) {
1656 fake_current_physical_time_
= fake_now
;
1660 base::TimeTicks fake_current_physical_time_
;
1663 class LayerTreeHostImplTestScrollbarAnimation
: public LayerTreeHostImplTest
{
1665 void SetupLayers(LayerTreeSettings settings
) {
1666 gfx::Size
viewport_size(10, 10);
1667 gfx::Size
content_size(100, 100);
1669 LayerTreeHostImplOverridePhysicalTime
* host_impl_override_time
=
1670 new LayerTreeHostImplOverridePhysicalTime(settings
, this, &proxy_
,
1671 shared_bitmap_manager_
.get(),
1672 &stats_instrumentation_
);
1673 host_impl_
= make_scoped_ptr(host_impl_override_time
);
1674 host_impl_
->InitializeRenderer(CreateOutputSurface());
1675 host_impl_
->SetViewportSize(viewport_size
);
1677 scoped_ptr
<LayerImpl
> root
=
1678 LayerImpl::Create(host_impl_
->active_tree(), 1);
1679 root
->SetBounds(viewport_size
);
1681 scoped_ptr
<LayerImpl
> scroll
=
1682 LayerImpl::Create(host_impl_
->active_tree(), 2);
1683 scroll
->SetScrollClipLayer(root
->id());
1684 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1685 root
->SetBounds(viewport_size
);
1686 scroll
->SetBounds(content_size
);
1687 scroll
->SetContentBounds(content_size
);
1688 scroll
->SetIsContainerForFixedPositionLayers(true);
1690 scoped_ptr
<LayerImpl
> contents
=
1691 LayerImpl::Create(host_impl_
->active_tree(), 3);
1692 contents
->SetDrawsContent(true);
1693 contents
->SetBounds(content_size
);
1694 contents
->SetContentBounds(content_size
);
1696 scoped_ptr
<SolidColorScrollbarLayerImpl
> scrollbar
=
1697 SolidColorScrollbarLayerImpl::Create(host_impl_
->active_tree(), 4,
1698 VERTICAL
, 10, 0, false, true);
1699 EXPECT_FLOAT_EQ(0.f
, scrollbar
->opacity());
1701 scroll
->AddChild(contents
.Pass());
1702 root
->AddChild(scroll
.Pass());
1703 root
->SetHasRenderSurface(true);
1704 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1705 root
->AddChild(scrollbar
.Pass());
1707 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1708 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
1710 host_impl_
->active_tree()->DidBecomeActive();
1714 void RunTest(LayerTreeSettings::ScrollbarAnimator animator
) {
1715 LayerTreeSettings settings
;
1716 settings
.scrollbar_animator
= animator
;
1717 settings
.scrollbar_fade_delay_ms
= 20;
1718 settings
.scrollbar_fade_duration_ms
= 20;
1720 SetupLayers(settings
);
1722 base::TimeTicks fake_now
= base::TimeTicks::Now();
1724 EXPECT_FALSE(did_request_animate_
);
1725 EXPECT_FALSE(did_request_redraw_
);
1726 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1727 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1729 // If no scroll happened during a scroll gesture, it should have no effect.
1730 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1731 host_impl_
->ScrollEnd();
1732 EXPECT_FALSE(did_request_animate_
);
1733 EXPECT_FALSE(did_request_redraw_
);
1734 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1735 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1737 // After a scroll, a scrollbar animation should be scheduled about 20ms from
1739 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1740 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 5));
1741 EXPECT_FALSE(did_request_animate_
);
1742 EXPECT_TRUE(did_request_redraw_
);
1743 did_request_redraw_
= false;
1744 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1745 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1747 host_impl_
->ScrollEnd();
1748 EXPECT_FALSE(did_request_animate_
);
1749 EXPECT_FALSE(did_request_redraw_
);
1750 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1751 requested_animation_delay_
);
1752 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1754 fake_now
+= requested_animation_delay_
;
1755 requested_animation_delay_
= base::TimeDelta();
1756 animation_task_
.Run();
1757 animation_task_
= base::Closure();
1758 EXPECT_TRUE(did_request_animate_
);
1759 did_request_animate_
= false;
1760 EXPECT_FALSE(did_request_redraw_
);
1762 // After the scrollbar animation begins, we should start getting redraws.
1763 host_impl_
->Animate(fake_now
);
1764 EXPECT_TRUE(did_request_animate_
);
1765 did_request_animate_
= false;
1766 EXPECT_TRUE(did_request_redraw_
);
1767 did_request_redraw_
= false;
1768 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1769 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1771 // Setting the scroll offset outside a scroll should also cause the
1772 // scrollbar to appear and to schedule a scrollbar animation.
1773 host_impl_
->InnerViewportScrollLayer()->PushScrollOffsetFromMainThread(
1774 gfx::ScrollOffset(5, 5));
1775 EXPECT_FALSE(did_request_animate_
);
1776 EXPECT_FALSE(did_request_redraw_
);
1777 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1778 requested_animation_delay_
);
1779 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1780 requested_animation_delay_
= base::TimeDelta();
1781 animation_task_
= base::Closure();
1783 // Scrollbar animation is not triggered unnecessarily.
1784 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
);
1785 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(5, 0));
1786 EXPECT_FALSE(did_request_animate_
);
1787 EXPECT_TRUE(did_request_redraw_
);
1788 did_request_redraw_
= false;
1789 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1790 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1792 host_impl_
->ScrollEnd();
1793 EXPECT_FALSE(did_request_animate_
);
1794 EXPECT_FALSE(did_request_redraw_
);
1795 EXPECT_EQ(base::TimeDelta(), requested_animation_delay_
);
1796 EXPECT_TRUE(animation_task_
.Equals(base::Closure()));
1798 // Changing page scale triggers scrollbar animation.
1799 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, 4.f
);
1800 host_impl_
->SetPageScaleOnActiveTree(1.1f
);
1801 EXPECT_FALSE(did_request_animate_
);
1802 EXPECT_FALSE(did_request_redraw_
);
1803 EXPECT_EQ(base::TimeDelta::FromMilliseconds(20),
1804 requested_animation_delay_
);
1805 EXPECT_FALSE(animation_task_
.Equals(base::Closure()));
1806 requested_animation_delay_
= base::TimeDelta();
1807 animation_task_
= base::Closure();
1811 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, LinearFade
) {
1812 RunTest(LayerTreeSettings::LINEAR_FADE
);
1815 TEST_F(LayerTreeHostImplTestScrollbarAnimation
, Thinning
) {
1816 RunTest(LayerTreeSettings::THINNING
);
1819 void LayerTreeHostImplTest::SetupMouseMoveAtWithDeviceScale(
1820 float device_scale_factor
) {
1821 LayerTreeSettings settings
;
1822 settings
.scrollbar_fade_delay_ms
= 500;
1823 settings
.scrollbar_fade_duration_ms
= 300;
1824 settings
.scrollbar_animator
= LayerTreeSettings::THINNING
;
1826 gfx::Size
viewport_size(300, 200);
1827 gfx::Size device_viewport_size
= gfx::ToFlooredSize(
1828 gfx::ScaleSize(viewport_size
, device_scale_factor
));
1829 gfx::Size
content_size(1000, 1000);
1831 CreateHostImpl(settings
, CreateOutputSurface());
1832 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
1833 host_impl_
->SetViewportSize(device_viewport_size
);
1835 scoped_ptr
<LayerImpl
> root
=
1836 LayerImpl::Create(host_impl_
->active_tree(), 1);
1837 root
->SetBounds(viewport_size
);
1838 root
->SetHasRenderSurface(true);
1840 scoped_ptr
<LayerImpl
> scroll
=
1841 LayerImpl::Create(host_impl_
->active_tree(), 2);
1842 scroll
->SetScrollClipLayer(root
->id());
1843 scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
1844 scroll
->SetBounds(content_size
);
1845 scroll
->SetContentBounds(content_size
);
1846 scroll
->SetIsContainerForFixedPositionLayers(true);
1848 scoped_ptr
<LayerImpl
> contents
=
1849 LayerImpl::Create(host_impl_
->active_tree(), 3);
1850 contents
->SetDrawsContent(true);
1851 contents
->SetBounds(content_size
);
1852 contents
->SetContentBounds(content_size
);
1854 // The scrollbar is on the right side.
1855 scoped_ptr
<PaintedScrollbarLayerImpl
> scrollbar
=
1856 PaintedScrollbarLayerImpl::Create(host_impl_
->active_tree(), 5, VERTICAL
);
1857 scrollbar
->SetDrawsContent(true);
1858 scrollbar
->SetBounds(gfx::Size(15, viewport_size
.height()));
1859 scrollbar
->SetContentBounds(gfx::Size(15, viewport_size
.height()));
1860 scrollbar
->SetPosition(gfx::Point(285, 0));
1862 scroll
->AddChild(contents
.Pass());
1863 root
->AddChild(scroll
.Pass());
1864 scrollbar
->SetScrollLayerAndClipLayerByIds(2, 1);
1865 root
->AddChild(scrollbar
.Pass());
1867 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
1868 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
1870 host_impl_
->active_tree()->DidBecomeActive();
1873 LayerImpl
* root_scroll
=
1874 host_impl_
->active_tree()->InnerViewportScrollLayer();
1875 ASSERT_TRUE(root_scroll
->scrollbar_animation_controller());
1876 ScrollbarAnimationControllerThinning
* scrollbar_animation_controller
=
1877 static_cast<ScrollbarAnimationControllerThinning
*>(
1878 root_scroll
->scrollbar_animation_controller());
1879 scrollbar_animation_controller
->set_mouse_move_distance_for_test(100.f
);
1881 host_impl_
->MouseMoveAt(gfx::Point(1, 1));
1882 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1884 host_impl_
->MouseMoveAt(gfx::Point(200, 50));
1885 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1887 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1888 EXPECT_FALSE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1890 scrollbar_animation_controller
->set_mouse_move_distance_for_test(102.f
);
1891 host_impl_
->MouseMoveAt(gfx::Point(184, 100));
1892 EXPECT_TRUE(scrollbar_animation_controller
->mouse_is_near_scrollbar());
1894 did_request_redraw_
= false;
1895 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1896 host_impl_
->MouseMoveAt(gfx::Point(290, 100));
1897 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1898 host_impl_
->MouseMoveAt(gfx::Point(290, 120));
1899 EXPECT_EQ(2, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1900 host_impl_
->MouseMoveAt(gfx::Point(150, 120));
1901 EXPECT_EQ(0, host_impl_
->scroll_layer_id_when_mouse_over_scrollbar());
1904 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf1
) {
1905 SetupMouseMoveAtWithDeviceScale(1.f
);
1908 TEST_F(LayerTreeHostImplTest
, MouseMoveAtWithDeviceScaleOf2
) {
1909 SetupMouseMoveAtWithDeviceScale(2.f
);
1912 TEST_F(LayerTreeHostImplTest
, CompositorFrameMetadata
) {
1913 SetupScrollAndContentsLayers(gfx::Size(100, 100));
1914 host_impl_
->SetViewportSize(gfx::Size(50, 50));
1915 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
1918 CompositorFrameMetadata metadata
=
1919 host_impl_
->MakeCompositorFrameMetadata();
1920 EXPECT_EQ(gfx::Vector2dF(), metadata
.root_scroll_offset
);
1921 EXPECT_EQ(1.f
, metadata
.page_scale_factor
);
1922 EXPECT_EQ(gfx::SizeF(50.f
, 50.f
), metadata
.scrollable_viewport_size
);
1923 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1924 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1925 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1926 EXPECT_FALSE(metadata
.root_overflow_x_hidden
);
1927 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
1930 // Scrolling should update metadata immediately.
1931 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
1932 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
1933 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
1935 CompositorFrameMetadata metadata
=
1936 host_impl_
->MakeCompositorFrameMetadata();
1937 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1939 host_impl_
->ScrollEnd();
1941 CompositorFrameMetadata metadata
=
1942 host_impl_
->MakeCompositorFrameMetadata();
1943 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1946 // Root "overflow: hidden" properties should be reflected on the outer
1947 // viewport scroll layer.
1949 host_impl_
->active_tree()
1950 ->OuterViewportScrollLayer()
1951 ->set_user_scrollable_horizontal(false);
1952 CompositorFrameMetadata metadata
=
1953 host_impl_
->MakeCompositorFrameMetadata();
1954 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
1955 EXPECT_FALSE(metadata
.root_overflow_y_hidden
);
1957 host_impl_
->active_tree()
1958 ->OuterViewportScrollLayer()
1959 ->set_user_scrollable_vertical(false);
1960 metadata
= host_impl_
->MakeCompositorFrameMetadata();
1961 EXPECT_TRUE(metadata
.root_overflow_x_hidden
);
1962 EXPECT_TRUE(metadata
.root_overflow_y_hidden
);
1965 // Page scale should update metadata correctly (shrinking only the viewport).
1966 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
1967 host_impl_
->PinchGestureBegin();
1968 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
1969 host_impl_
->PinchGestureEnd();
1970 host_impl_
->ScrollEnd();
1972 CompositorFrameMetadata metadata
=
1973 host_impl_
->MakeCompositorFrameMetadata();
1974 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1975 EXPECT_EQ(2.f
, metadata
.page_scale_factor
);
1976 EXPECT_EQ(gfx::SizeF(25.f
, 25.f
), metadata
.scrollable_viewport_size
);
1977 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1978 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1979 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1982 // Likewise if set from the main thread.
1983 host_impl_
->ProcessScrollDeltas();
1984 host_impl_
->active_tree()->PushPageScaleFromMainThread(4.f
, 0.5f
, 4.f
);
1985 host_impl_
->SetPageScaleOnActiveTree(4.f
);
1987 CompositorFrameMetadata metadata
=
1988 host_impl_
->MakeCompositorFrameMetadata();
1989 EXPECT_EQ(gfx::Vector2dF(0.f
, 10.f
), metadata
.root_scroll_offset
);
1990 EXPECT_EQ(4.f
, metadata
.page_scale_factor
);
1991 EXPECT_EQ(gfx::SizeF(12.5f
, 12.5f
), metadata
.scrollable_viewport_size
);
1992 EXPECT_EQ(gfx::SizeF(100.f
, 100.f
), metadata
.root_layer_size
);
1993 EXPECT_EQ(0.5f
, metadata
.min_page_scale_factor
);
1994 EXPECT_EQ(4.f
, metadata
.max_page_scale_factor
);
1998 class DidDrawCheckLayer
: public LayerImpl
{
2000 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
2001 return make_scoped_ptr(new DidDrawCheckLayer(tree_impl
, id
));
2004 bool WillDraw(DrawMode draw_mode
, ResourceProvider
* provider
) override
{
2005 will_draw_called_
= true;
2006 if (will_draw_returns_false_
)
2008 return LayerImpl::WillDraw(draw_mode
, provider
);
2011 void AppendQuads(RenderPass
* render_pass
,
2012 AppendQuadsData
* append_quads_data
) override
{
2013 append_quads_called_
= true;
2014 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2017 void DidDraw(ResourceProvider
* provider
) override
{
2018 did_draw_called_
= true;
2019 LayerImpl::DidDraw(provider
);
2022 bool will_draw_called() const { return will_draw_called_
; }
2023 bool append_quads_called() const { return append_quads_called_
; }
2024 bool did_draw_called() const { return did_draw_called_
; }
2026 void set_will_draw_returns_false() { will_draw_returns_false_
= true; }
2028 void ClearDidDrawCheck() {
2029 will_draw_called_
= false;
2030 append_quads_called_
= false;
2031 did_draw_called_
= false;
2034 static void IgnoreResult(scoped_ptr
<CopyOutputResult
> result
) {}
2036 void AddCopyRequest() {
2037 ScopedPtrVector
<CopyOutputRequest
> requests
;
2039 CopyOutputRequest::CreateRequest(base::Bind(&IgnoreResult
)));
2040 SetHasRenderSurface(true);
2041 PassCopyRequests(&requests
);
2045 DidDrawCheckLayer(LayerTreeImpl
* tree_impl
, int id
)
2046 : LayerImpl(tree_impl
, id
),
2047 will_draw_returns_false_(false),
2048 will_draw_called_(false),
2049 append_quads_called_(false),
2050 did_draw_called_(false) {
2051 SetBounds(gfx::Size(10, 10));
2052 SetContentBounds(gfx::Size(10, 10));
2053 SetDrawsContent(true);
2054 draw_properties().visible_content_rect
= gfx::Rect(0, 0, 10, 10);
2058 bool will_draw_returns_false_
;
2059 bool will_draw_called_
;
2060 bool append_quads_called_
;
2061 bool did_draw_called_
;
2064 TEST_F(LayerTreeHostImplTest
, WillDrawReturningFalseDoesNotCall
) {
2065 // The root layer is always drawn, so run this test on a child layer that
2066 // will be masked out by the root layer's bounds.
2067 host_impl_
->active_tree()->SetRootLayer(
2068 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2069 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2070 host_impl_
->active_tree()->root_layer());
2072 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2073 root
->SetHasRenderSurface(true);
2074 DidDrawCheckLayer
* layer
=
2075 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2078 LayerTreeHostImpl::FrameData frame
;
2079 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2080 host_impl_
->DrawLayers(&frame
);
2081 host_impl_
->DidDrawAllLayers(frame
);
2083 EXPECT_TRUE(layer
->will_draw_called());
2084 EXPECT_TRUE(layer
->append_quads_called());
2085 EXPECT_TRUE(layer
->did_draw_called());
2088 host_impl_
->SetViewportDamage(gfx::Rect(10, 10));
2091 LayerTreeHostImpl::FrameData frame
;
2093 layer
->set_will_draw_returns_false();
2094 layer
->ClearDidDrawCheck();
2096 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2097 host_impl_
->DrawLayers(&frame
);
2098 host_impl_
->DidDrawAllLayers(frame
);
2100 EXPECT_TRUE(layer
->will_draw_called());
2101 EXPECT_FALSE(layer
->append_quads_called());
2102 EXPECT_FALSE(layer
->did_draw_called());
2106 TEST_F(LayerTreeHostImplTest
, DidDrawNotCalledOnHiddenLayer
) {
2107 // The root layer is always drawn, so run this test on a child layer that
2108 // will be masked out by the root layer's bounds.
2109 host_impl_
->active_tree()->SetRootLayer(
2110 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2111 DidDrawCheckLayer
* root
= static_cast<DidDrawCheckLayer
*>(
2112 host_impl_
->active_tree()->root_layer());
2113 root
->SetMasksToBounds(true);
2114 root
->SetHasRenderSurface(true);
2115 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2116 DidDrawCheckLayer
* layer
=
2117 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2118 // Ensure visible_content_rect for layer is empty.
2119 layer
->SetPosition(gfx::PointF(100.f
, 100.f
));
2120 layer
->SetBounds(gfx::Size(10, 10));
2121 layer
->SetContentBounds(gfx::Size(10, 10));
2123 LayerTreeHostImpl::FrameData frame
;
2125 EXPECT_FALSE(layer
->will_draw_called());
2126 EXPECT_FALSE(layer
->did_draw_called());
2128 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2129 host_impl_
->DrawLayers(&frame
);
2130 host_impl_
->DidDrawAllLayers(frame
);
2132 EXPECT_FALSE(layer
->will_draw_called());
2133 EXPECT_FALSE(layer
->did_draw_called());
2135 EXPECT_TRUE(layer
->visible_content_rect().IsEmpty());
2137 // Ensure visible_content_rect for layer is not empty
2138 layer
->SetPosition(gfx::PointF());
2140 EXPECT_FALSE(layer
->will_draw_called());
2141 EXPECT_FALSE(layer
->did_draw_called());
2143 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2144 host_impl_
->DrawLayers(&frame
);
2145 host_impl_
->DidDrawAllLayers(frame
);
2147 EXPECT_TRUE(layer
->will_draw_called());
2148 EXPECT_TRUE(layer
->did_draw_called());
2150 EXPECT_FALSE(layer
->visible_content_rect().IsEmpty());
2153 TEST_F(LayerTreeHostImplTest
, WillDrawNotCalledOnOccludedLayer
) {
2154 gfx::Size
big_size(1000, 1000);
2155 host_impl_
->SetViewportSize(big_size
);
2157 host_impl_
->active_tree()->SetRootLayer(
2158 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2159 DidDrawCheckLayer
* root
=
2160 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2162 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2163 DidDrawCheckLayer
* occluded_layer
=
2164 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2166 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2167 root
->SetHasRenderSurface(true);
2168 DidDrawCheckLayer
* top_layer
=
2169 static_cast<DidDrawCheckLayer
*>(root
->children()[1]);
2170 // This layer covers the occluded_layer above. Make this layer large so it can
2172 top_layer
->SetBounds(big_size
);
2173 top_layer
->SetContentBounds(big_size
);
2174 top_layer
->SetContentsOpaque(true);
2176 LayerTreeHostImpl::FrameData frame
;
2178 EXPECT_FALSE(occluded_layer
->will_draw_called());
2179 EXPECT_FALSE(occluded_layer
->did_draw_called());
2180 EXPECT_FALSE(top_layer
->will_draw_called());
2181 EXPECT_FALSE(top_layer
->did_draw_called());
2183 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2184 host_impl_
->DrawLayers(&frame
);
2185 host_impl_
->DidDrawAllLayers(frame
);
2187 EXPECT_FALSE(occluded_layer
->will_draw_called());
2188 EXPECT_FALSE(occluded_layer
->did_draw_called());
2189 EXPECT_TRUE(top_layer
->will_draw_called());
2190 EXPECT_TRUE(top_layer
->did_draw_called());
2193 TEST_F(LayerTreeHostImplTest
, DidDrawCalledOnAllLayers
) {
2194 host_impl_
->active_tree()->SetRootLayer(
2195 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2196 DidDrawCheckLayer
* root
=
2197 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2199 root
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 2));
2200 root
->SetHasRenderSurface(true);
2201 DidDrawCheckLayer
* layer1
=
2202 static_cast<DidDrawCheckLayer
*>(root
->children()[0]);
2204 layer1
->AddChild(DidDrawCheckLayer::Create(host_impl_
->active_tree(), 3));
2205 DidDrawCheckLayer
* layer2
=
2206 static_cast<DidDrawCheckLayer
*>(layer1
->children()[0]);
2208 layer1
->SetHasRenderSurface(true);
2209 layer1
->SetShouldFlattenTransform(true);
2211 EXPECT_FALSE(root
->did_draw_called());
2212 EXPECT_FALSE(layer1
->did_draw_called());
2213 EXPECT_FALSE(layer2
->did_draw_called());
2215 LayerTreeHostImpl::FrameData frame
;
2216 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
2217 host_impl_
->active_tree()->root_layer());
2218 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2219 host_impl_
->DrawLayers(&frame
);
2220 host_impl_
->DidDrawAllLayers(frame
);
2222 EXPECT_TRUE(root
->did_draw_called());
2223 EXPECT_TRUE(layer1
->did_draw_called());
2224 EXPECT_TRUE(layer2
->did_draw_called());
2226 EXPECT_NE(root
->render_surface(), layer1
->render_surface());
2227 EXPECT_TRUE(layer1
->render_surface());
2230 class MissingTextureAnimatingLayer
: public DidDrawCheckLayer
{
2232 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
2235 bool had_incomplete_tile
,
2237 ResourceProvider
* resource_provider
) {
2238 return make_scoped_ptr(new MissingTextureAnimatingLayer(tree_impl
,
2241 had_incomplete_tile
,
2243 resource_provider
));
2246 void AppendQuads(RenderPass
* render_pass
,
2247 AppendQuadsData
* append_quads_data
) override
{
2248 LayerImpl::AppendQuads(render_pass
, append_quads_data
);
2249 if (had_incomplete_tile_
)
2250 append_quads_data
->num_incomplete_tiles
++;
2252 append_quads_data
->num_missing_tiles
++;
2256 MissingTextureAnimatingLayer(LayerTreeImpl
* tree_impl
,
2259 bool had_incomplete_tile
,
2261 ResourceProvider
* resource_provider
)
2262 : DidDrawCheckLayer(tree_impl
, id
),
2263 tile_missing_(tile_missing
),
2264 had_incomplete_tile_(had_incomplete_tile
) {
2266 AddAnimatedTransformToLayer(this, 10.0, 3, 0);
2270 bool had_incomplete_tile_
;
2273 struct PrepareToDrawSuccessTestCase
{
2275 bool has_missing_tile
= false;
2276 bool has_incomplete_tile
= false;
2277 bool is_animating
= false;
2278 bool has_copy_request
= false;
2280 bool high_res_required
= false;
2282 State layer_between
;
2284 DrawResult expected_result
;
2286 explicit PrepareToDrawSuccessTestCase(DrawResult result
)
2287 : expected_result(result
) {}
2290 TEST_F(LayerTreeHostImplTest
, PrepareToDrawSucceedsAndFails
) {
2291 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2294 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2295 // 1. Animated layer first.
2296 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2297 cases
.back().layer_before
.is_animating
= true;
2298 // 2. Animated layer between.
2299 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2300 cases
.back().layer_between
.is_animating
= true;
2301 // 3. Animated layer last.
2302 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2303 cases
.back().layer_after
.is_animating
= true;
2304 // 4. Missing tile first.
2305 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2306 cases
.back().layer_before
.has_missing_tile
= true;
2307 // 5. Missing tile between.
2308 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2309 cases
.back().layer_between
.has_missing_tile
= true;
2310 // 6. Missing tile last.
2311 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2312 cases
.back().layer_after
.has_missing_tile
= true;
2313 // 7. Incomplete tile first.
2314 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2315 cases
.back().layer_before
.has_incomplete_tile
= true;
2316 // 8. Incomplete tile between.
2317 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2318 cases
.back().layer_between
.has_incomplete_tile
= true;
2319 // 9. Incomplete tile last.
2320 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2321 cases
.back().layer_after
.has_incomplete_tile
= true;
2322 // 10. Animation with missing tile.
2324 PrepareToDrawSuccessTestCase(DRAW_ABORTED_CHECKERBOARD_ANIMATIONS
));
2325 cases
.back().layer_between
.has_missing_tile
= true;
2326 cases
.back().layer_between
.is_animating
= true;
2327 // 11. Animation with incomplete tile.
2328 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2329 cases
.back().layer_between
.has_incomplete_tile
= true;
2330 cases
.back().layer_between
.is_animating
= true;
2332 // 12. High res required.
2333 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2334 cases
.back().high_res_required
= true;
2335 // 13. High res required with incomplete tile.
2337 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2338 cases
.back().high_res_required
= true;
2339 cases
.back().layer_between
.has_incomplete_tile
= true;
2340 // 14. High res required with missing tile.
2342 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2343 cases
.back().high_res_required
= true;
2344 cases
.back().layer_between
.has_missing_tile
= true;
2346 // 15. High res required is higher priority than animating missing tiles.
2348 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2349 cases
.back().high_res_required
= true;
2350 cases
.back().layer_between
.has_missing_tile
= true;
2351 cases
.back().layer_after
.has_missing_tile
= true;
2352 cases
.back().layer_after
.is_animating
= true;
2353 // 16. High res required is higher priority than animating missing tiles.
2355 PrepareToDrawSuccessTestCase(DRAW_ABORTED_MISSING_HIGH_RES_CONTENT
));
2356 cases
.back().high_res_required
= true;
2357 cases
.back().layer_between
.has_missing_tile
= true;
2358 cases
.back().layer_before
.has_missing_tile
= true;
2359 cases
.back().layer_before
.is_animating
= true;
2361 host_impl_
->active_tree()->SetRootLayer(
2362 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2363 DidDrawCheckLayer
* root
=
2364 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2365 root
->SetHasRenderSurface(true);
2367 LayerTreeHostImpl::FrameData frame
;
2368 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2369 host_impl_
->DrawLayers(&frame
);
2370 host_impl_
->DidDrawAllLayers(frame
);
2371 host_impl_
->SwapBuffers(frame
);
2373 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2374 const auto& testcase
= cases
[i
];
2375 std::vector
<LayerImpl
*> to_remove
;
2376 for (auto* child
: root
->children())
2377 to_remove
.push_back(child
);
2378 for (auto* child
: to_remove
)
2379 root
->RemoveChild(child
);
2381 std::ostringstream scope
;
2382 scope
<< "Test case: " << i
;
2383 SCOPED_TRACE(scope
.str());
2385 root
->AddChild(MissingTextureAnimatingLayer::Create(
2386 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2387 testcase
.layer_before
.has_incomplete_tile
,
2388 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2389 DidDrawCheckLayer
* before
=
2390 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2391 if (testcase
.layer_before
.has_copy_request
)
2392 before
->AddCopyRequest();
2394 root
->AddChild(MissingTextureAnimatingLayer::Create(
2395 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2396 testcase
.layer_between
.has_incomplete_tile
,
2397 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2398 DidDrawCheckLayer
* between
=
2399 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2400 if (testcase
.layer_between
.has_copy_request
)
2401 between
->AddCopyRequest();
2403 root
->AddChild(MissingTextureAnimatingLayer::Create(
2404 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2405 testcase
.layer_after
.has_incomplete_tile
,
2406 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2407 DidDrawCheckLayer
* after
=
2408 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2409 if (testcase
.layer_after
.has_copy_request
)
2410 after
->AddCopyRequest();
2412 if (testcase
.high_res_required
)
2413 host_impl_
->SetRequiresHighResToDraw();
2415 LayerTreeHostImpl::FrameData frame
;
2416 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2417 host_impl_
->DrawLayers(&frame
);
2418 host_impl_
->DidDrawAllLayers(frame
);
2419 host_impl_
->SwapBuffers(frame
);
2423 TEST_F(LayerTreeHostImplTest
,
2424 PrepareToDrawWhenDrawAndSwapFullViewportEveryFrame
) {
2425 CreateHostImpl(DefaultSettings(),
2426 FakeOutputSurface::CreateAlwaysDrawAndSwap3d());
2427 EXPECT_TRUE(host_impl_
->output_surface()
2429 .draw_and_swap_full_viewport_every_frame
);
2431 std::vector
<PrepareToDrawSuccessTestCase
> cases
;
2434 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2435 // 1. Animation with missing tile.
2436 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2437 cases
.back().layer_between
.has_missing_tile
= true;
2438 cases
.back().layer_between
.is_animating
= true;
2439 // 2. High res required with incomplete tile.
2440 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2441 cases
.back().high_res_required
= true;
2442 cases
.back().layer_between
.has_incomplete_tile
= true;
2443 // 3. High res required with missing tile.
2444 cases
.push_back(PrepareToDrawSuccessTestCase(DRAW_SUCCESS
));
2445 cases
.back().high_res_required
= true;
2446 cases
.back().layer_between
.has_missing_tile
= true;
2448 host_impl_
->active_tree()->SetRootLayer(
2449 DidDrawCheckLayer::Create(host_impl_
->active_tree(), 1));
2450 DidDrawCheckLayer
* root
=
2451 static_cast<DidDrawCheckLayer
*>(host_impl_
->active_tree()->root_layer());
2452 root
->SetHasRenderSurface(true);
2454 LayerTreeHostImpl::FrameData frame
;
2455 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
2456 host_impl_
->DrawLayers(&frame
);
2457 host_impl_
->DidDrawAllLayers(frame
);
2458 host_impl_
->SwapBuffers(frame
);
2460 for (size_t i
= 0; i
< cases
.size(); ++i
) {
2461 const auto& testcase
= cases
[i
];
2462 std::vector
<LayerImpl
*> to_remove
;
2463 for (auto* child
: root
->children())
2464 to_remove
.push_back(child
);
2465 for (auto* child
: to_remove
)
2466 root
->RemoveChild(child
);
2468 std::ostringstream scope
;
2469 scope
<< "Test case: " << i
;
2470 SCOPED_TRACE(scope
.str());
2472 root
->AddChild(MissingTextureAnimatingLayer::Create(
2473 host_impl_
->active_tree(), 2, testcase
.layer_before
.has_missing_tile
,
2474 testcase
.layer_before
.has_incomplete_tile
,
2475 testcase
.layer_before
.is_animating
, host_impl_
->resource_provider()));
2476 DidDrawCheckLayer
* before
=
2477 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2478 if (testcase
.layer_before
.has_copy_request
)
2479 before
->AddCopyRequest();
2481 root
->AddChild(MissingTextureAnimatingLayer::Create(
2482 host_impl_
->active_tree(), 3, testcase
.layer_between
.has_missing_tile
,
2483 testcase
.layer_between
.has_incomplete_tile
,
2484 testcase
.layer_between
.is_animating
, host_impl_
->resource_provider()));
2485 DidDrawCheckLayer
* between
=
2486 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2487 if (testcase
.layer_between
.has_copy_request
)
2488 between
->AddCopyRequest();
2490 root
->AddChild(MissingTextureAnimatingLayer::Create(
2491 host_impl_
->active_tree(), 4, testcase
.layer_after
.has_missing_tile
,
2492 testcase
.layer_after
.has_incomplete_tile
,
2493 testcase
.layer_after
.is_animating
, host_impl_
->resource_provider()));
2494 DidDrawCheckLayer
* after
=
2495 static_cast<DidDrawCheckLayer
*>(root
->children().back());
2496 if (testcase
.layer_after
.has_copy_request
)
2497 after
->AddCopyRequest();
2499 if (testcase
.high_res_required
)
2500 host_impl_
->SetRequiresHighResToDraw();
2502 LayerTreeHostImpl::FrameData frame
;
2503 EXPECT_EQ(testcase
.expected_result
, host_impl_
->PrepareToDraw(&frame
));
2504 host_impl_
->DrawLayers(&frame
);
2505 host_impl_
->DidDrawAllLayers(frame
);
2506 host_impl_
->SwapBuffers(frame
);
2510 TEST_F(LayerTreeHostImplTest
, ScrollRootIgnored
) {
2511 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
2512 root
->SetScrollClipLayer(Layer::INVALID_ID
);
2513 root
->SetHasRenderSurface(true);
2514 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
2517 // Scroll event is ignored because layer is not scrollable.
2518 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
2519 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
2520 EXPECT_FALSE(did_request_redraw_
);
2521 EXPECT_FALSE(did_request_commit_
);
2524 // TODO(bokan): Convert these tests to create inner and outer viewports.
2525 class LayerTreeHostImplTopControlsTest
: public LayerTreeHostImplTest
{
2527 LayerTreeHostImplTopControlsTest()
2528 // Make the clip size the same as the layer (content) size so the layer is
2530 : layer_size_(10, 10),
2531 clip_size_(layer_size_
),
2532 top_controls_height_(50) {
2533 viewport_size_
= gfx::Size(clip_size_
.width(),
2534 clip_size_
.height() + top_controls_height_
);
2537 bool CreateHostImpl(const LayerTreeSettings
& settings
,
2538 scoped_ptr
<OutputSurface
> output_surface
) override
{
2540 LayerTreeHostImplTest::CreateHostImpl(settings
, output_surface
.Pass());
2542 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
2543 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2548 void SetupTopControlsAndScrollLayer() {
2549 scoped_ptr
<LayerImpl
> root
=
2550 LayerImpl::Create(host_impl_
->active_tree(), 1);
2551 scoped_ptr
<LayerImpl
> root_clip
=
2552 LayerImpl::Create(host_impl_
->active_tree(), 2);
2553 root_clip
->SetBounds(clip_size_
);
2554 root
->SetScrollClipLayer(root_clip
->id());
2555 root
->SetBounds(layer_size_
);
2556 root
->SetContentBounds(layer_size_
);
2557 root
->SetPosition(gfx::PointF());
2558 root
->SetDrawsContent(false);
2559 root
->SetIsContainerForFixedPositionLayers(true);
2560 int inner_viewport_scroll_layer_id
= root
->id();
2561 int page_scale_layer_id
= root_clip
->id();
2562 root_clip
->SetHasRenderSurface(true);
2563 root_clip
->AddChild(root
.Pass());
2564 root_clip
->SetHasRenderSurface(true);
2565 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2566 host_impl_
->active_tree()->SetViewportLayersFromIds(
2567 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2569 // Set a viewport size that is large enough to contain both the top controls
2570 // and some content.
2571 host_impl_
->SetViewportSize(viewport_size_
);
2572 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2574 host_impl_
->DidChangeTopControlsPosition();
2576 host_impl_
->CreatePendingTree();
2577 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2579 LayerImpl::Create(host_impl_
->sync_tree(), 1);
2581 LayerImpl::Create(host_impl_
->sync_tree(), 2);
2582 root_clip
->SetBounds(clip_size_
);
2583 root
->SetScrollClipLayer(root_clip
->id());
2584 root
->SetBounds(layer_size_
);
2585 root
->SetContentBounds(layer_size_
);
2586 root
->SetPosition(gfx::PointF());
2587 root
->SetDrawsContent(false);
2588 root
->SetIsContainerForFixedPositionLayers(true);
2589 inner_viewport_scroll_layer_id
= root
->id();
2590 page_scale_layer_id
= root_clip
->id();
2591 root_clip
->AddChild(root
.Pass());
2592 host_impl_
->sync_tree()->SetRootLayer(root_clip
.Pass());
2593 host_impl_
->sync_tree()->SetViewportLayersFromIds(
2594 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2596 // Set a viewport size that is large enough to contain both the top controls
2597 // and some content.
2598 host_impl_
->SetViewportSize(viewport_size_
);
2599 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2600 host_impl_
->DidChangeTopControlsPosition();
2603 void SetupTopControlsAndScrollLayerWithVirtualViewport(
2604 const gfx::Size
& inner_viewport_size
,
2605 const gfx::Size
& outer_viewport_size
,
2606 const gfx::Size
& scroll_layer_size
) {
2607 CreateHostImpl(settings_
, CreateOutputSurface());
2608 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2609 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
2610 host_impl_
->DidChangeTopControlsPosition();
2612 scoped_ptr
<LayerImpl
> root
=
2613 LayerImpl::Create(host_impl_
->active_tree(), 1);
2614 scoped_ptr
<LayerImpl
> root_clip
=
2615 LayerImpl::Create(host_impl_
->active_tree(), 2);
2616 scoped_ptr
<LayerImpl
> page_scale
=
2617 LayerImpl::Create(host_impl_
->active_tree(), 3);
2619 scoped_ptr
<LayerImpl
> outer_scroll
=
2620 LayerImpl::Create(host_impl_
->active_tree(), 4);
2621 scoped_ptr
<LayerImpl
> outer_clip
=
2622 LayerImpl::Create(host_impl_
->active_tree(), 5);
2624 root_clip
->SetBounds(inner_viewport_size
);
2625 root
->SetScrollClipLayer(root_clip
->id());
2626 root
->SetBounds(outer_viewport_size
);
2627 root
->SetContentBounds(outer_viewport_size
);
2628 root
->SetPosition(gfx::PointF());
2629 root
->SetDrawsContent(false);
2630 root
->SetIsContainerForFixedPositionLayers(true);
2631 root_clip
->SetHasRenderSurface(true);
2632 outer_clip
->SetBounds(outer_viewport_size
);
2633 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
2634 outer_scroll
->SetBounds(scroll_layer_size
);
2635 outer_scroll
->SetContentBounds(scroll_layer_size
);
2636 outer_scroll
->SetPosition(gfx::PointF());
2637 outer_scroll
->SetDrawsContent(false);
2638 outer_scroll
->SetIsContainerForFixedPositionLayers(true);
2640 int inner_viewport_scroll_layer_id
= root
->id();
2641 int outer_viewport_scroll_layer_id
= outer_scroll
->id();
2642 int page_scale_layer_id
= page_scale
->id();
2644 outer_clip
->AddChild(outer_scroll
.Pass());
2645 root
->AddChild(outer_clip
.Pass());
2646 page_scale
->AddChild(root
.Pass());
2647 root_clip
->AddChild(page_scale
.Pass());
2649 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
2650 host_impl_
->active_tree()->SetViewportLayersFromIds(
2651 Layer::INVALID_ID
, page_scale_layer_id
, inner_viewport_scroll_layer_id
,
2652 outer_viewport_scroll_layer_id
);
2654 host_impl_
->SetViewportSize(inner_viewport_size
);
2655 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2656 EXPECT_EQ(inner_viewport_size
, root_clip_ptr
->bounds());
2660 gfx::Size layer_size_
;
2661 gfx::Size clip_size_
;
2662 gfx::Size viewport_size_
;
2663 float top_controls_height_
;
2665 LayerTreeSettings settings_
;
2666 }; // class LayerTreeHostImplTopControlsTest
2668 TEST_F(LayerTreeHostImplTopControlsTest
, ScrollTopControlsByFractionalAmount
) {
2669 SetupTopControlsAndScrollLayerWithVirtualViewport(
2670 gfx::Size(10, 10), gfx::Size(10, 10), gfx::Size(10, 10));
2673 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2674 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2676 // Make the test scroll delta a fractional amount, to verify that the
2677 // fixed container size delta is (1) non-zero, and (2) fractional, and
2678 // (3) matches the movement of the top controls.
2679 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 5.25f
);
2680 host_impl_
->top_controls_manager()->ScrollBegin();
2681 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2682 host_impl_
->top_controls_manager()->ScrollEnd();
2684 LayerImpl
* inner_viewport_scroll_layer
=
2685 host_impl_
->active_tree()->InnerViewportScrollLayer();
2686 DCHECK(inner_viewport_scroll_layer
);
2687 host_impl_
->ScrollEnd();
2688 EXPECT_FLOAT_EQ(top_controls_scroll_delta
.y(),
2689 inner_viewport_scroll_layer
->FixedContainerSizeDelta().y());
2692 // In this test, the outer viewport is initially unscrollable. We test that a
2693 // scroll initiated on the inner viewport, causing the top controls to show and
2694 // thus making the outer viewport scrollable, still scrolls the outer viewport.
2695 TEST_F(LayerTreeHostImplTopControlsTest
,
2696 TopControlsOuterViewportBecomesScrollable
) {
2697 SetupTopControlsAndScrollLayerWithVirtualViewport(
2698 gfx::Size(10, 50), gfx::Size(10, 50), gfx::Size(10, 100));
2701 LayerImpl
* inner_scroll
=
2702 host_impl_
->active_tree()->InnerViewportScrollLayer();
2703 LayerImpl
* inner_container
=
2704 host_impl_
->active_tree()->InnerViewportContainerLayer();
2705 LayerImpl
* outer_scroll
=
2706 host_impl_
->active_tree()->OuterViewportScrollLayer();
2707 LayerImpl
* outer_container
=
2708 host_impl_
->active_tree()->OuterViewportContainerLayer();
2710 // Need SetDrawsContent so ScrollBegin's hit test finds an actual layer.
2711 outer_scroll
->SetDrawsContent(true);
2712 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 1.f
, 2.f
);
2714 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2715 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2716 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 50.f
));
2718 // The entire scroll delta should have been used to hide the top controls.
2719 // The viewport layers should be resized back to their full sizes.
2720 EXPECT_EQ(0.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2721 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2722 EXPECT_EQ(100.f
, inner_container
->BoundsForScrolling().height());
2723 EXPECT_EQ(100.f
, outer_container
->BoundsForScrolling().height());
2725 // The inner viewport should be scrollable by 50px * page_scale.
2726 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, 100.f
));
2727 EXPECT_EQ(50.f
, inner_scroll
->CurrentScrollOffset().y());
2728 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2729 EXPECT_EQ(gfx::ScrollOffset(), outer_scroll
->MaxScrollOffset());
2731 host_impl_
->ScrollEnd();
2733 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2734 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2735 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
2737 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2739 // The entire scroll delta should have been used to show the top controls.
2740 // The outer viewport should be resized to accomodate and scrolled to the
2741 // bottom of the document to keep the viewport in place.
2742 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2743 EXPECT_EQ(50.f
, outer_container
->BoundsForScrolling().height());
2744 EXPECT_EQ(50.f
, inner_container
->BoundsForScrolling().height());
2745 EXPECT_EQ(25.f
, outer_scroll
->CurrentScrollOffset().y());
2746 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2748 // Now when we continue scrolling, make sure the outer viewport gets scrolled
2749 // since it wasn't scrollable when the scroll began.
2750 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -20.f
));
2751 EXPECT_EQ(15.f
, outer_scroll
->CurrentScrollOffset().y());
2752 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2754 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -30.f
));
2755 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2756 EXPECT_EQ(25.f
, inner_scroll
->CurrentScrollOffset().y());
2758 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.f
, -50.f
));
2759 host_impl_
->ScrollEnd();
2761 EXPECT_EQ(0.f
, outer_scroll
->CurrentScrollOffset().y());
2762 EXPECT_EQ(0.f
, inner_scroll
->CurrentScrollOffset().y());
2765 // Test that the fixed position container delta is appropriately adjusted
2766 // by the top controls showing/hiding and page scale doesn't affect it.
2767 TEST_F(LayerTreeHostImplTopControlsTest
, FixedContainerDelta
) {
2768 SetupTopControlsAndScrollLayerWithVirtualViewport(
2769 gfx::Size(100, 100), gfx::Size(100, 100), gfx::Size(100, 100));
2772 float page_scale
= 1.5f
;
2773 LayerImpl
* outer_viewport_scroll_layer
=
2774 host_impl_
->active_tree()->OuterViewportScrollLayer();
2776 // Zoom in, since the fixed container is the outer viewport, the delta should
2778 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
, 2.f
);
2780 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2781 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2783 // Scroll down, the top controls hiding should expand the viewport size so
2784 // the delta should be equal to the scroll distance.
2785 gfx::Vector2dF
top_controls_scroll_delta(0.f
, 20.f
);
2786 host_impl_
->top_controls_manager()->ScrollBegin();
2787 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2788 EXPECT_FLOAT_EQ(top_controls_height_
- top_controls_scroll_delta
.y(),
2789 host_impl_
->top_controls_manager()->ContentTopOffset());
2790 EXPECT_VECTOR_EQ(top_controls_scroll_delta
,
2791 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2792 host_impl_
->ScrollEnd();
2794 // Scroll past the maximum extent. The delta shouldn't be greater than the
2795 // top controls height.
2796 host_impl_
->top_controls_manager()->ScrollBegin();
2797 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2798 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2799 host_impl_
->top_controls_manager()->ScrollBy(top_controls_scroll_delta
);
2800 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2801 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, top_controls_height_
),
2802 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2803 host_impl_
->ScrollEnd();
2805 // Scroll in the direction to make the top controls show.
2806 host_impl_
->top_controls_manager()->ScrollBegin();
2807 host_impl_
->top_controls_manager()->ScrollBy(-top_controls_scroll_delta
);
2808 EXPECT_EQ(top_controls_scroll_delta
.y(),
2809 host_impl_
->top_controls_manager()->ContentTopOffset());
2811 gfx::Vector2dF(0, top_controls_height_
- top_controls_scroll_delta
.y()),
2812 outer_viewport_scroll_layer
->FixedContainerSizeDelta());
2813 host_impl_
->top_controls_manager()->ScrollEnd();
2816 // Test that if a scrollable sublayer doesn't consume the scroll,
2817 // top controls should hide when scrolling down.
2818 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollableSublayer
) {
2819 gfx::Size
sub_content_size(100, 400);
2820 gfx::Size
sub_content_layer_size(100, 300);
2821 SetupTopControlsAndScrollLayerWithVirtualViewport(
2822 gfx::Size(100, 50), gfx::Size(100, 100), gfx::Size(100, 100));
2825 // Show top controls
2826 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2828 LayerImpl
* outer_viewport_scroll_layer
=
2829 host_impl_
->active_tree()->OuterViewportScrollLayer();
2830 int id
= outer_viewport_scroll_layer
->id();
2832 scoped_ptr
<LayerImpl
> child
=
2833 LayerImpl::Create(host_impl_
->active_tree(), id
+ 2);
2834 scoped_ptr
<LayerImpl
> child_clip
=
2835 LayerImpl::Create(host_impl_
->active_tree(), id
+ 3);
2837 child_clip
->SetBounds(sub_content_layer_size
);
2838 child
->SetScrollClipLayer(child_clip
->id());
2839 child
->SetBounds(sub_content_size
);
2840 child
->SetContentBounds(sub_content_size
);
2841 child
->SetPosition(gfx::PointF());
2842 child
->SetDrawsContent(true);
2843 child
->SetIsContainerForFixedPositionLayers(true);
2845 // scroll child to limit
2846 child
->SetScrollDelta(gfx::Vector2dF(0, 100.f
));
2847 child_clip
->AddChild(child
.Pass());
2848 outer_viewport_scroll_layer
->AddChild(child_clip
.Pass());
2850 // Scroll 25px to hide top controls
2851 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
2852 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
2853 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
2854 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
2855 host_impl_
->ScrollEnd();
2857 // Top controls should be hidden
2858 EXPECT_EQ(scroll_delta
.y(),
2859 top_controls_height_
-
2860 host_impl_
->top_controls_manager()->ContentTopOffset());
2863 // Ensure setting the top controls position explicitly using the setters on the
2864 // TreeImpl correctly affects the top controls manager and viewport bounds.
2865 TEST_F(LayerTreeHostImplTopControlsTest
, PositionTopControlsExplicitly
) {
2866 CreateHostImpl(settings_
, CreateOutputSurface());
2867 SetupTopControlsAndScrollLayer();
2870 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2871 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2872 30.f
/ top_controls_height_
);
2873 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2874 EXPECT_FLOAT_EQ(30.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2875 EXPECT_FLOAT_EQ(-20.f
,
2876 host_impl_
->top_controls_manager()->ControlsTopOffset());
2878 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2879 EXPECT_FLOAT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2880 EXPECT_FLOAT_EQ(-50.f
,
2881 host_impl_
->top_controls_manager()->ControlsTopOffset());
2883 host_impl_
->DidChangeTopControlsPosition();
2885 // Now that top controls have moved, expect the clip to resize.
2886 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2887 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2890 // Test that the top_controls delta and sent delta are appropriately
2891 // applied on sync tree activation. The total top controls offset shouldn't
2892 // change after the activation.
2893 TEST_F(LayerTreeHostImplTopControlsTest
, ApplyDeltaOnTreeActivation
) {
2894 CreateHostImpl(settings_
, CreateOutputSurface());
2895 SetupTopControlsAndScrollLayer();
2898 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2899 20.f
/ top_controls_height_
);
2900 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2901 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(
2902 15.f
/ top_controls_height_
);
2903 host_impl_
->active_tree()
2904 ->top_controls_shown_ratio()
2905 ->PullDeltaForMainThread();
2906 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2907 host_impl_
->sync_tree()->PushTopControlsFromMainThread(15.f
/
2908 top_controls_height_
);
2910 host_impl_
->DidChangeTopControlsPosition();
2911 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2912 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2913 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2915 host_impl_
->ActivateSyncTree();
2917 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2918 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2919 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2922 -15.f
, host_impl_
->active_tree()->top_controls_shown_ratio()->Delta() *
2923 top_controls_height_
);
2926 host_impl_
->active_tree()->top_controls_shown_ratio()->ActiveBase() *
2927 top_controls_height_
);
2930 // Test that changing the top controls layout height is correctly applied to
2931 // the inner viewport container bounds. That is, the top controls layout
2932 // height is the amount that the inner viewport container was shrunk outside
2933 // the compositor to accommodate the top controls.
2934 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsLayoutHeightChanged
) {
2935 CreateHostImpl(settings_
, CreateOutputSurface());
2936 SetupTopControlsAndScrollLayer();
2939 host_impl_
->sync_tree()->PushTopControlsFromMainThread(1.f
);
2940 host_impl_
->sync_tree()->set_top_controls_shrink_blink_size(true);
2942 host_impl_
->active_tree()->top_controls_shown_ratio()->PushFromMainThread(
2944 host_impl_
->active_tree()->top_controls_shown_ratio()->PushPendingToActive();
2945 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(0.f
);
2947 host_impl_
->DidChangeTopControlsPosition();
2948 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2949 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2950 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2952 host_impl_
->sync_tree()->root_layer()->SetBounds(
2953 gfx::Size(root_clip_ptr
->bounds().width(),
2954 root_clip_ptr
->bounds().height() - 50.f
));
2956 host_impl_
->ActivateSyncTree();
2958 root_clip_ptr
= host_impl_
->active_tree()->root_layer();
2959 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2961 // The total bounds should remain unchanged since the bounds delta should
2962 // account for the difference between the layout height and the current
2963 // top controls offset.
2964 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
2965 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 50.f
), root_clip_ptr
->bounds_delta());
2967 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
2968 host_impl_
->DidChangeTopControlsPosition();
2970 EXPECT_EQ(1.f
, host_impl_
->top_controls_manager()->TopControlsShownRatio());
2971 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->TopControlsHeight());
2972 EXPECT_EQ(50.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
2973 EXPECT_VECTOR_EQ(gfx::Vector2dF(0.f
, 0.f
), root_clip_ptr
->bounds_delta());
2974 EXPECT_EQ(gfx::Size(viewport_size_
.width(), viewport_size_
.height() - 50.f
),
2975 root_clip_ptr
->bounds());
2978 // Test that showing/hiding the top controls when the viewport is fully scrolled
2979 // doesn't incorrectly change the viewport offset due to clamping from changing
2981 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsViewportOffsetClamping
) {
2982 SetupTopControlsAndScrollLayerWithVirtualViewport(
2983 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
2986 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
2988 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
2989 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
2991 // Scroll the viewports to max scroll offset.
2992 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
2993 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
2995 gfx::ScrollOffset viewport_offset
=
2996 host_impl_
->active_tree()->TotalScrollOffset();
2997 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(), viewport_offset
);
2999 // Hide the top controls by 25px.
3000 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3001 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3002 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3003 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3005 // scrolling down at the max extents no longer hides the top controls
3006 EXPECT_EQ(1.f
, host_impl_
->active_tree()->CurrentTopControlsShownRatio());
3008 // forcefully hide the top controls by 25px
3009 host_impl_
->top_controls_manager()->ScrollBy(scroll_delta
);
3010 host_impl_
->ScrollEnd();
3012 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3013 top_controls_height_
-
3014 host_impl_
->top_controls_manager()->ContentTopOffset());
3016 inner_scroll
->ClampScrollToMaxScrollOffset();
3017 outer_scroll
->ClampScrollToMaxScrollOffset();
3019 // We should still be fully scrolled.
3020 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3021 host_impl_
->active_tree()->TotalScrollOffset());
3023 viewport_offset
= host_impl_
->active_tree()->TotalScrollOffset();
3025 // Bring the top controls down by 25px.
3026 scroll_delta
= gfx::Vector2dF(0.f
, -25.f
);
3027 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3028 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3029 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3030 host_impl_
->ScrollEnd();
3032 // The viewport offset shouldn't have changed.
3033 EXPECT_EQ(viewport_offset
,
3034 host_impl_
->active_tree()->TotalScrollOffset());
3036 // Scroll the viewports to max scroll offset.
3037 outer_scroll
->SetScrollDelta(gfx::Vector2dF(0, 200.f
));
3038 inner_scroll
->SetScrollDelta(gfx::Vector2dF(100, 100.f
));
3039 EXPECT_EQ(host_impl_
->active_tree()->TotalMaxScrollOffset(),
3040 host_impl_
->active_tree()->TotalScrollOffset());
3043 // Test that the top controls coming in and out maintains the same aspect ratio
3044 // between the inner and outer viewports.
3045 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsAspectRatio
) {
3046 SetupTopControlsAndScrollLayerWithVirtualViewport(
3047 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3050 EXPECT_FLOAT_EQ(top_controls_height_
,
3051 host_impl_
->top_controls_manager()->ContentTopOffset());
3053 gfx::Vector2dF
scroll_delta(0.f
, 25.f
);
3054 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3055 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3056 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3057 host_impl_
->ScrollEnd();
3059 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3060 top_controls_height_
-
3061 host_impl_
->top_controls_manager()->ContentTopOffset());
3063 // Top controls were hidden by 25px so the inner viewport should have expanded
3065 LayerImpl
* outer_container
=
3066 host_impl_
->active_tree()->OuterViewportContainerLayer();
3067 LayerImpl
* inner_container
=
3068 host_impl_
->active_tree()->InnerViewportContainerLayer();
3069 EXPECT_EQ(gfx::Size(100, 100+25), inner_container
->BoundsForScrolling());
3071 // Outer viewport should match inner's aspect ratio. The bounds are ceiled.
3072 float aspect_ratio
= inner_container
->BoundsForScrolling().width() /
3073 inner_container
->BoundsForScrolling().height();
3074 gfx::Size expected
= gfx::ToCeiledSize(gfx::SizeF(200, 200 / aspect_ratio
));
3075 EXPECT_EQ(expected
, outer_container
->BoundsForScrolling());
3077 host_impl_
->InnerViewportScrollLayer()->BoundsForScrolling());
3080 // Test that scrolling the outer viewport affects the top controls.
3081 TEST_F(LayerTreeHostImplTopControlsTest
, TopControlsScrollOuterViewport
) {
3082 SetupTopControlsAndScrollLayerWithVirtualViewport(
3083 gfx::Size(100, 100), gfx::Size(200, 200), gfx::Size(200, 400));
3086 EXPECT_EQ(top_controls_height_
,
3087 host_impl_
->top_controls_manager()->ContentTopOffset());
3089 // Send a gesture scroll that will scroll the outer viewport, make sure the
3090 // top controls get scrolled.
3091 gfx::Vector2dF
scroll_delta(0.f
, 15.f
);
3092 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3093 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3094 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3095 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3096 host_impl_
->CurrentlyScrollingLayer());
3097 host_impl_
->ScrollEnd();
3099 EXPECT_FLOAT_EQ(scroll_delta
.y(),
3100 top_controls_height_
-
3101 host_impl_
->top_controls_manager()->ContentTopOffset());
3103 scroll_delta
= gfx::Vector2dF(0.f
, 50.f
);
3104 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3105 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3106 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3108 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ContentTopOffset());
3109 EXPECT_EQ(host_impl_
->OuterViewportScrollLayer(),
3110 host_impl_
->CurrentlyScrollingLayer());
3112 host_impl_
->ScrollEnd();
3114 // Position the viewports such that the inner viewport will be scrolled.
3115 gfx::Vector2dF
inner_viewport_offset(0.f
, 25.f
);
3116 host_impl_
->OuterViewportScrollLayer()->SetScrollDelta(gfx::Vector2dF());
3117 host_impl_
->InnerViewportScrollLayer()->SetScrollDelta(inner_viewport_offset
);
3119 scroll_delta
= gfx::Vector2dF(0.f
, -65.f
);
3120 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3121 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3122 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3124 EXPECT_EQ(top_controls_height_
,
3125 host_impl_
->top_controls_manager()->ContentTopOffset());
3127 inner_viewport_offset
.y() + (scroll_delta
.y() + top_controls_height_
),
3128 host_impl_
->InnerViewportScrollLayer()->ScrollDelta().y());
3130 host_impl_
->ScrollEnd();
3133 TEST_F(LayerTreeHostImplTopControlsTest
,
3134 ScrollNonScrollableRootWithTopControls
) {
3135 CreateHostImpl(settings_
, CreateOutputSurface());
3136 SetupTopControlsAndScrollLayer();
3139 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3140 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3142 host_impl_
->top_controls_manager()->ScrollBegin();
3143 host_impl_
->top_controls_manager()->ScrollBy(gfx::Vector2dF(0.f
, 50.f
));
3144 host_impl_
->top_controls_manager()->ScrollEnd();
3145 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ContentTopOffset());
3146 // Now that top controls have moved, expect the clip to resize.
3147 LayerImpl
* root_clip_ptr
= host_impl_
->active_tree()->root_layer();
3148 EXPECT_EQ(viewport_size_
, root_clip_ptr
->bounds());
3150 host_impl_
->ScrollEnd();
3152 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3153 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3155 float scroll_increment_y
= -25.f
;
3156 host_impl_
->top_controls_manager()->ScrollBegin();
3157 host_impl_
->top_controls_manager()->ScrollBy(
3158 gfx::Vector2dF(0.f
, scroll_increment_y
));
3159 EXPECT_FLOAT_EQ(-scroll_increment_y
,
3160 host_impl_
->top_controls_manager()->ContentTopOffset());
3161 // Now that top controls have moved, expect the clip to resize.
3162 EXPECT_EQ(gfx::Size(viewport_size_
.width(),
3163 viewport_size_
.height() + scroll_increment_y
),
3164 root_clip_ptr
->bounds());
3166 host_impl_
->top_controls_manager()->ScrollBy(
3167 gfx::Vector2dF(0.f
, scroll_increment_y
));
3168 host_impl_
->top_controls_manager()->ScrollEnd();
3169 EXPECT_FLOAT_EQ(-2 * scroll_increment_y
,
3170 host_impl_
->top_controls_manager()->ContentTopOffset());
3171 // Now that top controls have moved, expect the clip to resize.
3172 EXPECT_EQ(clip_size_
, root_clip_ptr
->bounds());
3174 host_impl_
->ScrollEnd();
3176 // Verify the layer is once-again non-scrollable.
3178 gfx::ScrollOffset(),
3179 host_impl_
->active_tree()->InnerViewportScrollLayer()->MaxScrollOffset());
3181 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3182 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3185 TEST_F(LayerTreeHostImplTest
, ScrollNonCompositedRoot
) {
3186 // Test the configuration where a non-composited root layer is embedded in a
3187 // scrollable outer layer.
3188 gfx::Size
surface_size(10, 10);
3189 gfx::Size
contents_size(20, 20);
3191 scoped_ptr
<LayerImpl
> content_layer
=
3192 LayerImpl::Create(host_impl_
->active_tree(), 1);
3193 content_layer
->SetDrawsContent(true);
3194 content_layer
->SetPosition(gfx::PointF());
3195 content_layer
->SetBounds(contents_size
);
3196 content_layer
->SetContentBounds(contents_size
);
3197 content_layer
->SetContentsScale(2.f
, 2.f
);
3199 scoped_ptr
<LayerImpl
> scroll_clip_layer
=
3200 LayerImpl::Create(host_impl_
->active_tree(), 3);
3201 scroll_clip_layer
->SetBounds(surface_size
);
3203 scoped_ptr
<LayerImpl
> scroll_layer
=
3204 LayerImpl::Create(host_impl_
->active_tree(), 2);
3205 scroll_layer
->SetScrollClipLayer(3);
3206 scroll_layer
->SetBounds(contents_size
);
3207 scroll_layer
->SetContentBounds(contents_size
);
3208 scroll_layer
->SetPosition(gfx::PointF());
3209 scroll_layer
->AddChild(content_layer
.Pass());
3210 scroll_clip_layer
->AddChild(scroll_layer
.Pass());
3212 scroll_clip_layer
->SetHasRenderSurface(true);
3213 host_impl_
->active_tree()->SetRootLayer(scroll_clip_layer
.Pass());
3214 host_impl_
->SetViewportSize(surface_size
);
3217 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3218 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3219 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3220 host_impl_
->ScrollEnd();
3221 EXPECT_TRUE(did_request_redraw_
);
3222 EXPECT_TRUE(did_request_commit_
);
3225 TEST_F(LayerTreeHostImplTest
, ScrollChildCallsCommitAndRedraw
) {
3226 gfx::Size
surface_size(10, 10);
3227 gfx::Size
contents_size(20, 20);
3228 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3229 root
->SetBounds(surface_size
);
3230 root
->SetContentBounds(contents_size
);
3231 root
->AddChild(CreateScrollableLayer(2, contents_size
, root
.get()));
3232 root
->SetHasRenderSurface(true);
3233 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3234 host_impl_
->SetViewportSize(surface_size
);
3237 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3238 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3239 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
3240 host_impl_
->ScrollEnd();
3241 EXPECT_TRUE(did_request_redraw_
);
3242 EXPECT_TRUE(did_request_commit_
);
3245 TEST_F(LayerTreeHostImplTest
, ScrollMissesChild
) {
3246 gfx::Size
surface_size(10, 10);
3247 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3248 root
->AddChild(CreateScrollableLayer(2, surface_size
, root
.get()));
3249 root
->SetHasRenderSurface(true);
3250 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3251 host_impl_
->SetViewportSize(surface_size
);
3254 // Scroll event is ignored because the input coordinate is outside the layer
3256 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3257 host_impl_
->ScrollBegin(gfx::Point(15, 5), InputHandler::WHEEL
));
3258 EXPECT_FALSE(did_request_redraw_
);
3259 EXPECT_FALSE(did_request_commit_
);
3262 TEST_F(LayerTreeHostImplTest
, ScrollMissesBackfacingChild
) {
3263 gfx::Size
surface_size(10, 10);
3264 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3265 root
->SetHasRenderSurface(true);
3266 scoped_ptr
<LayerImpl
> child
=
3267 CreateScrollableLayer(2, surface_size
, root
.get());
3268 host_impl_
->SetViewportSize(surface_size
);
3270 gfx::Transform matrix
;
3271 matrix
.RotateAboutXAxis(180.0);
3272 child
->SetTransform(matrix
);
3273 child
->SetDoubleSided(false);
3275 root
->AddChild(child
.Pass());
3276 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3279 // Scroll event is ignored because the scrollable layer is not facing the
3280 // viewer and there is nothing scrollable behind it.
3281 EXPECT_EQ(InputHandler::SCROLL_IGNORED
,
3282 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3283 EXPECT_FALSE(did_request_redraw_
);
3284 EXPECT_FALSE(did_request_commit_
);
3287 TEST_F(LayerTreeHostImplTest
, ScrollBlockedByContentLayer
) {
3288 gfx::Size
surface_size(10, 10);
3289 scoped_ptr
<LayerImpl
> clip_layer
=
3290 LayerImpl::Create(host_impl_
->active_tree(), 3);
3291 scoped_ptr
<LayerImpl
> content_layer
=
3292 CreateScrollableLayer(1, surface_size
, clip_layer
.get());
3293 content_layer
->SetShouldScrollOnMainThread(true);
3294 content_layer
->SetScrollClipLayer(Layer::INVALID_ID
);
3296 // Note: we can use the same clip layer for both since both calls to
3297 // CreateScrollableLayer() use the same surface size.
3298 scoped_ptr
<LayerImpl
> scroll_layer
=
3299 CreateScrollableLayer(2, surface_size
, clip_layer
.get());
3300 scroll_layer
->AddChild(content_layer
.Pass());
3301 clip_layer
->AddChild(scroll_layer
.Pass());
3302 clip_layer
->SetHasRenderSurface(true);
3304 host_impl_
->active_tree()->SetRootLayer(clip_layer
.Pass());
3305 host_impl_
->SetViewportSize(surface_size
);
3308 // Scrolling fails because the content layer is asking to be scrolled on the
3310 EXPECT_EQ(InputHandler::SCROLL_ON_MAIN_THREAD
,
3311 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3314 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnMainThread
) {
3315 gfx::Size
surface_size(20, 20);
3316 gfx::Size
viewport_size(10, 10);
3317 float page_scale
= 2.f
;
3318 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3319 scoped_ptr
<LayerImpl
> root_clip
=
3320 LayerImpl::Create(host_impl_
->active_tree(), 2);
3321 scoped_ptr
<LayerImpl
> root_scrolling
=
3322 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3323 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3324 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3325 root_clip
->AddChild(root_scrolling
.Pass());
3326 root
->AddChild(root_clip
.Pass());
3327 root
->SetHasRenderSurface(true);
3328 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3329 // The behaviour in this test assumes the page scale is applied at a layer
3330 // above the clip layer.
3331 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3333 host_impl_
->active_tree()->DidBecomeActive();
3334 host_impl_
->SetViewportSize(viewport_size
);
3337 LayerImpl
* root_scroll
=
3338 host_impl_
->active_tree()->InnerViewportScrollLayer();
3339 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3341 gfx::Vector2d
scroll_delta(0, 10);
3342 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3343 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3344 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3345 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3346 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3347 host_impl_
->ScrollEnd();
3349 // Set new page scale from main thread.
3350 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, page_scale
,
3353 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3354 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
3356 // The scroll range should also have been updated.
3357 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3359 // The page scale delta remains constant because the impl thread did not
3361 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3364 TEST_F(LayerTreeHostImplTest
, ScrollRootAndChangePageScaleOnImplThread
) {
3365 gfx::Size
surface_size(20, 20);
3366 gfx::Size
viewport_size(10, 10);
3367 float page_scale
= 2.f
;
3368 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3369 scoped_ptr
<LayerImpl
> root_clip
=
3370 LayerImpl::Create(host_impl_
->active_tree(), 2);
3371 scoped_ptr
<LayerImpl
> root_scrolling
=
3372 CreateScrollableLayer(3, surface_size
, root_clip
.get());
3373 EXPECT_EQ(viewport_size
, root_clip
->bounds());
3374 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3375 root_clip
->AddChild(root_scrolling
.Pass());
3376 root
->AddChild(root_clip
.Pass());
3377 root
->SetHasRenderSurface(true);
3378 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3379 // The behaviour in this test assumes the page scale is applied at a layer
3380 // above the clip layer.
3381 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 3,
3383 host_impl_
->active_tree()->DidBecomeActive();
3384 host_impl_
->SetViewportSize(viewport_size
);
3385 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 1.f
, page_scale
);
3388 LayerImpl
* root_scroll
=
3389 host_impl_
->active_tree()->InnerViewportScrollLayer();
3390 EXPECT_EQ(viewport_size
, root_scroll
->scroll_clip_layer()->bounds());
3392 gfx::Vector2d
scroll_delta(0, 10);
3393 gfx::Vector2d expected_scroll_delta
= scroll_delta
;
3394 gfx::ScrollOffset expected_max_scroll
= root_scroll
->MaxScrollOffset();
3395 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3396 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3397 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3398 host_impl_
->ScrollEnd();
3400 // Set new page scale on impl thread by pinching.
3401 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3402 host_impl_
->PinchGestureBegin();
3403 host_impl_
->PinchGestureUpdate(page_scale
, gfx::Point());
3404 host_impl_
->PinchGestureEnd();
3405 host_impl_
->ScrollEnd();
3408 // The scroll delta is not scaled because the main thread did not scale.
3409 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3410 ExpectContains(*scroll_info
.get(), root_scroll
->id(), expected_scroll_delta
);
3412 // The scroll range should also have been updated.
3413 EXPECT_EQ(expected_max_scroll
, root_scroll
->MaxScrollOffset());
3415 // The page scale delta should match the new scale on the impl side.
3416 EXPECT_EQ(page_scale
, host_impl_
->active_tree()->current_page_scale_factor());
3419 TEST_F(LayerTreeHostImplTest
, PageScaleDeltaAppliedToRootScrollLayerOnly
) {
3420 gfx::Size
surface_size(10, 10);
3421 float default_page_scale
= 1.f
;
3422 gfx::Transform default_page_scale_matrix
;
3423 default_page_scale_matrix
.Scale(default_page_scale
, default_page_scale
);
3425 float new_page_scale
= 2.f
;
3426 gfx::Transform new_page_scale_matrix
;
3427 new_page_scale_matrix
.Scale(new_page_scale
, new_page_scale
);
3429 // Create a normal scrollable root layer and another scrollable child layer.
3430 LayerImpl
* scroll
= SetupScrollAndContentsLayers(surface_size
);
3431 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
3432 LayerImpl
* child
= scroll
->children()[0];
3434 scoped_ptr
<LayerImpl
> scrollable_child_clip
=
3435 LayerImpl::Create(host_impl_
->active_tree(), 6);
3436 scoped_ptr
<LayerImpl
> scrollable_child
=
3437 CreateScrollableLayer(7, surface_size
, scrollable_child_clip
.get());
3438 scrollable_child_clip
->AddChild(scrollable_child
.Pass());
3439 child
->AddChild(scrollable_child_clip
.Pass());
3440 LayerImpl
* grand_child
= child
->children()[0];
3442 // Set new page scale on impl thread by pinching.
3443 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
3444 host_impl_
->PinchGestureBegin();
3445 host_impl_
->PinchGestureUpdate(new_page_scale
, gfx::Point());
3446 host_impl_
->PinchGestureEnd();
3447 host_impl_
->ScrollEnd();
3450 EXPECT_EQ(1.f
, root
->contents_scale_x());
3451 EXPECT_EQ(1.f
, root
->contents_scale_y());
3452 EXPECT_EQ(1.f
, scroll
->contents_scale_x());
3453 EXPECT_EQ(1.f
, scroll
->contents_scale_y());
3454 EXPECT_EQ(1.f
, child
->contents_scale_x());
3455 EXPECT_EQ(1.f
, child
->contents_scale_y());
3456 EXPECT_EQ(1.f
, grand_child
->contents_scale_x());
3457 EXPECT_EQ(1.f
, grand_child
->contents_scale_y());
3459 // Make sure all the layers are drawn with the page scale delta applied, i.e.,
3460 // the page scale delta on the root layer is applied hierarchically.
3461 LayerTreeHostImpl::FrameData frame
;
3462 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
3463 host_impl_
->DrawLayers(&frame
);
3464 host_impl_
->DidDrawAllLayers(frame
);
3466 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(0, 0));
3467 EXPECT_EQ(1.f
, root
->draw_transform().matrix().getDouble(1, 1));
3468 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(0, 0));
3469 EXPECT_EQ(new_page_scale
, scroll
->draw_transform().matrix().getDouble(1, 1));
3470 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(0, 0));
3471 EXPECT_EQ(new_page_scale
, child
->draw_transform().matrix().getDouble(1, 1));
3472 EXPECT_EQ(new_page_scale
,
3473 grand_child
->draw_transform().matrix().getDouble(0, 0));
3474 EXPECT_EQ(new_page_scale
,
3475 grand_child
->draw_transform().matrix().getDouble(1, 1));
3478 TEST_F(LayerTreeHostImplTest
, ScrollChildAndChangePageScaleOnMainThread
) {
3479 gfx::Size
surface_size(30, 30);
3480 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3481 root
->SetBounds(gfx::Size(5, 5));
3482 root
->SetHasRenderSurface(true);
3483 scoped_ptr
<LayerImpl
> root_scrolling
=
3484 LayerImpl::Create(host_impl_
->active_tree(), 2);
3485 root_scrolling
->SetBounds(surface_size
);
3486 root_scrolling
->SetContentBounds(surface_size
);
3487 root_scrolling
->SetScrollClipLayer(root
->id());
3488 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3489 LayerImpl
* root_scrolling_ptr
= root_scrolling
.get();
3490 root
->AddChild(root_scrolling
.Pass());
3491 int child_scroll_layer_id
= 3;
3492 scoped_ptr
<LayerImpl
> child_scrolling
= CreateScrollableLayer(
3493 child_scroll_layer_id
, surface_size
, root_scrolling_ptr
);
3494 LayerImpl
* child
= child_scrolling
.get();
3495 root_scrolling_ptr
->AddChild(child_scrolling
.Pass());
3496 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3497 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3499 host_impl_
->active_tree()->DidBecomeActive();
3500 host_impl_
->SetViewportSize(surface_size
);
3503 gfx::Vector2d
scroll_delta(0, 10);
3504 gfx::Vector2d
expected_scroll_delta(scroll_delta
);
3505 gfx::ScrollOffset
expected_max_scroll(child
->MaxScrollOffset());
3506 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3507 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3508 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3509 host_impl_
->ScrollEnd();
3511 float page_scale
= 2.f
;
3512 host_impl_
->active_tree()->PushPageScaleFromMainThread(page_scale
, 1.f
,
3517 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3519 *scroll_info
.get(), child_scroll_layer_id
, expected_scroll_delta
);
3521 // The scroll range should not have changed.
3522 EXPECT_EQ(child
->MaxScrollOffset(), expected_max_scroll
);
3524 // The page scale delta remains constant because the impl thread did not
3526 EXPECT_EQ(1.f
, host_impl_
->active_tree()->page_scale_delta());
3529 TEST_F(LayerTreeHostImplTest
, ScrollChildBeyondLimit
) {
3530 // Scroll a child layer beyond its maximum scroll range and make sure the
3531 // parent layer is scrolled on the axis on which the child was unable to
3533 gfx::Size
surface_size(10, 10);
3534 gfx::Size
content_size(20, 20);
3535 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3536 root
->SetBounds(surface_size
);
3537 root
->SetHasRenderSurface(true);
3538 scoped_ptr
<LayerImpl
> grand_child
=
3539 CreateScrollableLayer(3, content_size
, root
.get());
3541 scoped_ptr
<LayerImpl
> child
=
3542 CreateScrollableLayer(2, content_size
, root
.get());
3543 LayerImpl
* grand_child_layer
= grand_child
.get();
3544 child
->AddChild(grand_child
.Pass());
3546 LayerImpl
* child_layer
= child
.get();
3547 root
->AddChild(child
.Pass());
3548 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3549 host_impl_
->active_tree()->DidBecomeActive();
3550 host_impl_
->SetViewportSize(surface_size
);
3551 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 5));
3552 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(3, 0));
3556 gfx::Vector2d
scroll_delta(-8, -7);
3557 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3558 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3559 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3560 host_impl_
->ScrollEnd();
3562 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3563 host_impl_
->ProcessScrollDeltas();
3565 // The grand child should have scrolled up to its limit.
3566 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
3567 LayerImpl
* grand_child
= child
->children()[0];
3568 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -5));
3570 // The child should have only scrolled on the other axis.
3571 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(-3, 0));
3575 TEST_F(LayerTreeHostImplTest
, ScrollWithoutBubbling
) {
3576 // Scroll a child layer beyond its maximum scroll range and make sure the
3577 // the scroll doesn't bubble up to the parent layer.
3578 gfx::Size
surface_size(20, 20);
3579 gfx::Size
viewport_size(10, 10);
3580 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
3581 root
->SetHasRenderSurface(true);
3582 scoped_ptr
<LayerImpl
> root_scrolling
=
3583 CreateScrollableLayer(2, surface_size
, root
.get());
3584 root_scrolling
->SetIsContainerForFixedPositionLayers(true);
3586 scoped_ptr
<LayerImpl
> grand_child
=
3587 CreateScrollableLayer(4, surface_size
, root
.get());
3589 scoped_ptr
<LayerImpl
> child
=
3590 CreateScrollableLayer(3, surface_size
, root
.get());
3591 LayerImpl
* grand_child_layer
= grand_child
.get();
3592 child
->AddChild(grand_child
.Pass());
3594 LayerImpl
* child_layer
= child
.get();
3595 root_scrolling
->AddChild(child
.Pass());
3596 root
->AddChild(root_scrolling
.Pass());
3597 EXPECT_EQ(viewport_size
, root
->bounds());
3598 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
3599 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3601 host_impl_
->active_tree()->DidBecomeActive();
3602 host_impl_
->SetViewportSize(viewport_size
);
3604 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
3605 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
3609 gfx::Vector2d
scroll_delta(0, -10);
3610 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3611 host_impl_
->ScrollBegin(gfx::Point(),
3612 InputHandler::NON_BUBBLING_GESTURE
));
3613 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3614 host_impl_
->ScrollEnd();
3616 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3617 host_impl_
->ProcessScrollDeltas();
3619 // The grand child should have scrolled up to its limit.
3621 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
3622 LayerImpl
* grand_child
= child
->children()[0];
3623 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
3625 // The child should not have scrolled.
3626 ExpectNone(*scroll_info
.get(), child
->id());
3628 // The next time we scroll we should only scroll the parent.
3629 scroll_delta
= gfx::Vector2d(0, -3);
3630 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3631 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3632 InputHandler::NON_BUBBLING_GESTURE
));
3633 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3634 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3635 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
3636 host_impl_
->ScrollEnd();
3638 scroll_info
= host_impl_
->ProcessScrollDeltas();
3640 // The child should have scrolled up to its limit.
3641 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
3643 // The grand child should not have scrolled.
3644 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, -2));
3646 // After scrolling the parent, another scroll on the opposite direction
3647 // should still scroll the child.
3648 scroll_delta
= gfx::Vector2d(0, 7);
3649 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3650 host_impl_
->ScrollBegin(gfx::Point(5, 5),
3651 InputHandler::NON_BUBBLING_GESTURE
));
3652 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3653 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3654 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
3655 host_impl_
->ScrollEnd();
3657 scroll_info
= host_impl_
->ProcessScrollDeltas();
3659 // The grand child should have scrolled.
3660 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 5));
3662 // The child should not have scrolled.
3663 ExpectContains(*scroll_info
.get(), child
->id(), gfx::Vector2d(0, -3));
3666 // Scrolling should be adjusted from viewport space.
3667 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 2.f
, 2.f
);
3668 host_impl_
->SetPageScaleOnActiveTree(2.f
);
3670 scroll_delta
= gfx::Vector2d(0, -2);
3671 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3672 host_impl_
->ScrollBegin(gfx::Point(1, 1),
3673 InputHandler::NON_BUBBLING_GESTURE
));
3674 EXPECT_EQ(grand_child
, host_impl_
->CurrentlyScrollingLayer());
3675 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3676 host_impl_
->ScrollEnd();
3678 scroll_info
= host_impl_
->ProcessScrollDeltas();
3680 // Should have scrolled by half the amount in layer space (5 - 2/2)
3681 ExpectContains(*scroll_info
.get(), grand_child
->id(), gfx::Vector2d(0, 4));
3684 TEST_F(LayerTreeHostImplTest
, ScrollEventBubbling
) {
3685 // When we try to scroll a non-scrollable child layer, the scroll delta
3686 // should be applied to one of its ancestors if possible.
3687 gfx::Size
surface_size(10, 10);
3688 gfx::Size
content_size(20, 20);
3689 scoped_ptr
<LayerImpl
> root_clip
=
3690 LayerImpl::Create(host_impl_
->active_tree(), 3);
3691 root_clip
->SetHasRenderSurface(true);
3692 scoped_ptr
<LayerImpl
> root
=
3693 CreateScrollableLayer(1, content_size
, root_clip
.get());
3694 // Make 'root' the clip layer for child: since they have the same sizes the
3695 // child will have zero max_scroll_offset and scrolls will bubble.
3696 scoped_ptr
<LayerImpl
> child
=
3697 CreateScrollableLayer(2, content_size
, root
.get());
3698 child
->SetIsContainerForFixedPositionLayers(true);
3699 root
->SetBounds(content_size
);
3701 int root_scroll_id
= root
->id();
3702 root
->AddChild(child
.Pass());
3703 root_clip
->AddChild(root
.Pass());
3705 host_impl_
->SetViewportSize(surface_size
);
3706 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3707 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 2,
3709 host_impl_
->active_tree()->DidBecomeActive();
3712 gfx::Vector2d
scroll_delta(0, 4);
3713 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3714 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3715 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3716 host_impl_
->ScrollEnd();
3718 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3719 host_impl_
->ProcessScrollDeltas();
3721 // Only the root scroll should have scrolled.
3722 ASSERT_EQ(scroll_info
->scrolls
.size(), 1u);
3723 ExpectContains(*scroll_info
.get(), root_scroll_id
, scroll_delta
);
3727 TEST_F(LayerTreeHostImplTest
, ScrollBeforeRedraw
) {
3728 gfx::Size
surface_size(10, 10);
3729 scoped_ptr
<LayerImpl
> root_clip
=
3730 LayerImpl::Create(host_impl_
->active_tree(), 1);
3731 scoped_ptr
<LayerImpl
> root_scroll
=
3732 CreateScrollableLayer(2, surface_size
, root_clip
.get());
3733 root_scroll
->SetIsContainerForFixedPositionLayers(true);
3734 root_clip
->SetHasRenderSurface(true);
3735 root_clip
->AddChild(root_scroll
.Pass());
3736 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
3737 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 1, 2,
3739 host_impl_
->active_tree()->DidBecomeActive();
3740 host_impl_
->SetViewportSize(surface_size
);
3742 // Draw one frame and then immediately rebuild the layer tree to mimic a tree
3745 host_impl_
->active_tree()->DetachLayerTree();
3746 scoped_ptr
<LayerImpl
> root_clip2
=
3747 LayerImpl::Create(host_impl_
->active_tree(), 3);
3748 scoped_ptr
<LayerImpl
> root_scroll2
=
3749 CreateScrollableLayer(4, surface_size
, root_clip2
.get());
3750 root_scroll2
->SetIsContainerForFixedPositionLayers(true);
3751 root_clip2
->AddChild(root_scroll2
.Pass());
3752 root_clip2
->SetHasRenderSurface(true);
3753 host_impl_
->active_tree()->SetRootLayer(root_clip2
.Pass());
3754 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 4,
3756 host_impl_
->active_tree()->DidBecomeActive();
3758 // Scrolling should still work even though we did not draw yet.
3759 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3760 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
3763 TEST_F(LayerTreeHostImplTest
, ScrollAxisAlignedRotatedLayer
) {
3764 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3766 // Rotate the root layer 90 degrees counter-clockwise about its center.
3767 gfx::Transform rotate_transform
;
3768 rotate_transform
.Rotate(-90.0);
3769 host_impl_
->active_tree()->root_layer()->SetTransform(rotate_transform
);
3771 gfx::Size
surface_size(50, 50);
3772 host_impl_
->SetViewportSize(surface_size
);
3775 // Scroll to the right in screen coordinates with a gesture.
3776 gfx::Vector2d
gesture_scroll_delta(10, 0);
3777 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3778 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3779 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3780 host_impl_
->ScrollEnd();
3782 // The layer should have scrolled down in its local coordinates.
3783 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3784 ExpectContains(*scroll_info
.get(), scroll_layer
->id(),
3785 gfx::Vector2d(0, gesture_scroll_delta
.x()));
3787 // Reset and scroll down with the wheel.
3788 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3789 gfx::Vector2d
wheel_scroll_delta(0, 10);
3790 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3791 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3792 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3793 host_impl_
->ScrollEnd();
3795 // The layer should have scrolled down in its local coordinates.
3796 scroll_info
= host_impl_
->ProcessScrollDeltas();
3797 ExpectContains(*scroll_info
.get(),
3799 wheel_scroll_delta
);
3802 TEST_F(LayerTreeHostImplTest
, ScrollNonAxisAlignedRotatedLayer
) {
3803 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
3804 int child_clip_layer_id
= 6;
3805 int child_layer_id
= 7;
3806 float child_layer_angle
= -20.f
;
3808 // Create a child layer that is rotated to a non-axis-aligned angle.
3809 scoped_ptr
<LayerImpl
> clip_layer
=
3810 LayerImpl::Create(host_impl_
->active_tree(), child_clip_layer_id
);
3811 scoped_ptr
<LayerImpl
> child
= CreateScrollableLayer(
3812 child_layer_id
, scroll_layer
->content_bounds(), clip_layer
.get());
3813 gfx::Transform rotate_transform
;
3814 rotate_transform
.Translate(-50.0, -50.0);
3815 rotate_transform
.Rotate(child_layer_angle
);
3816 rotate_transform
.Translate(50.0, 50.0);
3817 clip_layer
->SetTransform(rotate_transform
);
3819 // Only allow vertical scrolling.
3820 clip_layer
->SetBounds(
3821 gfx::Size(child
->bounds().width(), child
->bounds().height() / 2));
3822 // The rotation depends on the layer's transform origin, and the child layer
3823 // is a different size than the clip, so make sure the clip layer's origin
3824 // lines up over the child.
3825 clip_layer
->SetTransformOrigin(gfx::Point3F(
3826 clip_layer
->bounds().width() * 0.5f
, clip_layer
->bounds().height(), 0.f
));
3827 LayerImpl
* child_ptr
= child
.get();
3828 clip_layer
->AddChild(child
.Pass());
3829 scroll_layer
->AddChild(clip_layer
.Pass());
3831 gfx::Size
surface_size(50, 50);
3832 host_impl_
->SetViewportSize(surface_size
);
3835 // Scroll down in screen coordinates with a gesture.
3836 gfx::Vector2d
gesture_scroll_delta(0, 10);
3837 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3838 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
3839 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3840 host_impl_
->ScrollEnd();
3842 // The child layer should have scrolled down in its local coordinates an
3843 // amount proportional to the angle between it and the input scroll delta.
3844 gfx::Vector2d
expected_scroll_delta(
3845 0, gesture_scroll_delta
.y() *
3846 std::cos(MathUtil::Deg2Rad(child_layer_angle
)));
3847 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3848 host_impl_
->ProcessScrollDeltas();
3849 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3851 // The root scroll layer should not have scrolled, because the input delta
3852 // was close to the layer's axis of movement.
3853 EXPECT_EQ(scroll_info
->scrolls
.size(), 1u);
3856 // Now reset and scroll the same amount horizontally.
3857 child_ptr
->SetScrollDelta(gfx::Vector2dF());
3858 gfx::Vector2d
gesture_scroll_delta(10, 0);
3859 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3860 host_impl_
->ScrollBegin(gfx::Point(1, 1), InputHandler::GESTURE
));
3861 host_impl_
->ScrollBy(gfx::Point(), gesture_scroll_delta
);
3862 host_impl_
->ScrollEnd();
3864 // The child layer should have scrolled down in its local coordinates an
3865 // amount proportional to the angle between it and the input scroll delta.
3866 gfx::Vector2d
expected_scroll_delta(
3867 0, -gesture_scroll_delta
.x() *
3868 std::sin(MathUtil::Deg2Rad(child_layer_angle
)));
3869 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
3870 host_impl_
->ProcessScrollDeltas();
3871 ExpectContains(*scroll_info
.get(), child_layer_id
, expected_scroll_delta
);
3873 // The root scroll layer should have scrolled more, since the input scroll
3874 // delta was mostly orthogonal to the child layer's vertical scroll axis.
3875 gfx::Vector2d
expected_root_scroll_delta(
3876 gesture_scroll_delta
.x() *
3877 std::pow(std::cos(MathUtil::Deg2Rad(child_layer_angle
)), 2),
3879 ExpectContains(*scroll_info
.get(),
3881 expected_root_scroll_delta
);
3885 TEST_F(LayerTreeHostImplTest
, ScrollScaledLayer
) {
3886 LayerImpl
* scroll_layer
=
3887 SetupScrollAndContentsLayers(gfx::Size(100, 100));
3889 // Scale the layer to twice its normal size.
3891 gfx::Transform scale_transform
;
3892 scale_transform
.Scale(scale
, scale
);
3893 scroll_layer
->SetTransform(scale_transform
);
3895 gfx::Size
surface_size(50, 50);
3896 host_impl_
->SetViewportSize(surface_size
);
3899 // Scroll down in screen coordinates with a gesture.
3900 gfx::Vector2d
scroll_delta(0, 10);
3901 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3902 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
3903 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
3904 host_impl_
->ScrollEnd();
3906 // The layer should have scrolled down in its local coordinates, but half the
3908 scoped_ptr
<ScrollAndScaleSet
> scroll_info
= host_impl_
->ProcessScrollDeltas();
3909 ExpectContains(*scroll_info
.get(),
3911 gfx::Vector2d(0, scroll_delta
.y() / scale
));
3913 // Reset and scroll down with the wheel.
3914 scroll_layer
->SetScrollDelta(gfx::Vector2dF());
3915 gfx::Vector2d
wheel_scroll_delta(0, 10);
3916 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
3917 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
3918 host_impl_
->ScrollBy(gfx::Point(), wheel_scroll_delta
);
3919 host_impl_
->ScrollEnd();
3921 // It should apply the scale factor to the scroll delta for the wheel event.
3922 scroll_info
= host_impl_
->ProcessScrollDeltas();
3923 ExpectContains(*scroll_info
.get(),
3925 wheel_scroll_delta
);
3928 TEST_F(LayerTreeHostImplTest
, ScrollViewportRounding
) {
3932 SetupScrollAndContentsLayers(gfx::Size(width
, height
));
3933 host_impl_
->active_tree()->InnerViewportContainerLayer()->SetBounds(
3934 gfx::Size(width
* scale
- 1, height
* scale
));
3935 host_impl_
->SetDeviceScaleFactor(scale
);
3936 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
3938 LayerImpl
* inner_viewport_scroll_layer
=
3939 host_impl_
->active_tree()->InnerViewportScrollLayer();
3940 EXPECT_EQ(gfx::ScrollOffset(0, 0),
3941 inner_viewport_scroll_layer
->MaxScrollOffset());
3944 class TestScrollOffsetDelegate
: public LayerScrollOffsetDelegate
{
3946 TestScrollOffsetDelegate()
3947 : page_scale_factor_(0.f
),
3948 min_page_scale_factor_(-1.f
),
3949 max_page_scale_factor_(-1.f
) {}
3951 ~TestScrollOffsetDelegate() override
{}
3953 gfx::ScrollOffset
GetTotalScrollOffset() override
{
3954 return getter_return_value_
;
3957 bool IsExternalFlingActive() const override
{ return false; }
3959 void UpdateRootLayerState(const gfx::ScrollOffset
& total_scroll_offset
,
3960 const gfx::ScrollOffset
& max_scroll_offset
,
3961 const gfx::SizeF
& scrollable_size
,
3962 float page_scale_factor
,
3963 float min_page_scale_factor
,
3964 float max_page_scale_factor
) override
{
3965 DCHECK(total_scroll_offset
.x() <= max_scroll_offset
.x());
3966 DCHECK(total_scroll_offset
.y() <= max_scroll_offset
.y());
3967 last_set_scroll_offset_
= total_scroll_offset
;
3968 max_scroll_offset_
= max_scroll_offset
;
3969 scrollable_size_
= scrollable_size
;
3970 page_scale_factor_
= page_scale_factor
;
3971 min_page_scale_factor_
= min_page_scale_factor
;
3972 max_page_scale_factor_
= max_page_scale_factor
;
3974 set_getter_return_value(last_set_scroll_offset_
);
3977 gfx::ScrollOffset
last_set_scroll_offset() {
3978 return last_set_scroll_offset_
;
3981 void set_getter_return_value(const gfx::ScrollOffset
& value
) {
3982 getter_return_value_
= value
;
3985 gfx::ScrollOffset
max_scroll_offset() const {
3986 return max_scroll_offset_
;
3989 gfx::SizeF
scrollable_size() const {
3990 return scrollable_size_
;
3993 float page_scale_factor() const {
3994 return page_scale_factor_
;
3997 float min_page_scale_factor() const {
3998 return min_page_scale_factor_
;
4001 float max_page_scale_factor() const {
4002 return max_page_scale_factor_
;
4006 gfx::ScrollOffset last_set_scroll_offset_
;
4007 gfx::ScrollOffset getter_return_value_
;
4008 gfx::ScrollOffset max_scroll_offset_
;
4009 gfx::SizeF scrollable_size_
;
4010 float page_scale_factor_
;
4011 float min_page_scale_factor_
;
4012 float max_page_scale_factor_
;
4015 TEST_F(LayerTreeHostImplTest
, RootLayerScrollOffsetDelegation
) {
4016 TestScrollOffsetDelegate scroll_delegate
;
4017 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4018 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4019 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4020 clip_layer
->SetBounds(gfx::Size(10, 20));
4022 // Setting the delegate results in the current scroll offset being set.
4023 gfx::Vector2dF
initial_scroll_delta(10.f
, 10.f
);
4024 scroll_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
4025 scroll_layer
->SetScrollDelta(initial_scroll_delta
);
4026 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4027 EXPECT_EQ(initial_scroll_delta
.ToString(),
4028 scroll_delegate
.last_set_scroll_offset().ToString());
4030 // Setting the delegate results in the scrollable_size, max_scroll_offset,
4031 // page_scale_factor and {min|max}_page_scale_factor being set.
4032 EXPECT_EQ(gfx::SizeF(100, 100), scroll_delegate
.scrollable_size());
4033 EXPECT_EQ(gfx::ScrollOffset(90, 80), scroll_delegate
.max_scroll_offset());
4034 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4035 EXPECT_EQ(0.f
, scroll_delegate
.min_page_scale_factor());
4036 EXPECT_EQ(0.f
, scroll_delegate
.max_page_scale_factor());
4038 // Updating page scale immediately updates the delegate.
4039 host_impl_
->active_tree()->PushPageScaleFromMainThread(2.f
, 0.5f
, 4.f
);
4040 EXPECT_EQ(2.f
, scroll_delegate
.page_scale_factor());
4041 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4042 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4043 host_impl_
->SetPageScaleOnActiveTree(2.f
* 1.5f
);
4044 EXPECT_EQ(3.f
, scroll_delegate
.page_scale_factor());
4045 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4046 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4047 host_impl_
->SetPageScaleOnActiveTree(2.f
);
4048 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4049 EXPECT_EQ(1.f
, scroll_delegate
.page_scale_factor());
4050 EXPECT_EQ(0.5f
, scroll_delegate
.min_page_scale_factor());
4051 EXPECT_EQ(4.f
, scroll_delegate
.max_page_scale_factor());
4053 // The pinch gesture doesn't put the delegate into a state where the scroll
4054 // offset is outside of the scroll range. (this is verified by DCHECKs in the
4056 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
4057 host_impl_
->PinchGestureBegin();
4058 host_impl_
->PinchGestureUpdate(2.f
, gfx::Point());
4059 host_impl_
->PinchGestureUpdate(.5f
, gfx::Point());
4060 host_impl_
->PinchGestureEnd();
4061 host_impl_
->ScrollEnd();
4063 // Scrolling should be relative to the offset as returned by the delegate.
4064 gfx::Vector2dF
scroll_delta(0.f
, 10.f
);
4065 gfx::ScrollOffset
current_offset(7.f
, 8.f
);
4067 scroll_delegate
.set_getter_return_value(current_offset
);
4068 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4069 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
4070 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4072 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4073 EXPECT_EQ(ScrollOffsetWithDelta(current_offset
, scroll_delta
),
4074 scroll_delegate
.last_set_scroll_offset());
4076 current_offset
= gfx::ScrollOffset(42.f
, 41.f
);
4077 scroll_delegate
.set_getter_return_value(current_offset
);
4078 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4079 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4080 EXPECT_EQ(current_offset
+ gfx::ScrollOffset(scroll_delta
),
4081 scroll_delegate
.last_set_scroll_offset());
4082 host_impl_
->ScrollEnd();
4083 scroll_delegate
.set_getter_return_value(gfx::ScrollOffset());
4084 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4086 // Forces a full tree synchronization and ensures that the scroll delegate
4087 // sees the correct size of the new tree.
4088 gfx::Size
new_size(42, 24);
4089 host_impl_
->CreatePendingTree();
4090 CreateScrollAndContentsLayers(host_impl_
->pending_tree(), new_size
);
4091 host_impl_
->ActivateSyncTree();
4092 EXPECT_EQ(new_size
, scroll_delegate
.scrollable_size());
4094 // Un-setting the delegate should propagate the delegate's current offset to
4095 // the root scrollable layer.
4096 current_offset
= gfx::ScrollOffset(13.f
, 12.f
);
4097 scroll_delegate
.set_getter_return_value(current_offset
);
4098 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4099 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4101 EXPECT_EQ(current_offset
.ToString(),
4102 scroll_layer
->CurrentScrollOffset().ToString());
4105 void CheckLayerScrollDelta(LayerImpl
* layer
, gfx::Vector2dF scroll_delta
) {
4106 const gfx::Transform target_space_transform
=
4107 layer
->draw_properties().target_space_transform
;
4108 EXPECT_TRUE(target_space_transform
.IsScaleOrTranslation());
4109 gfx::Point translated_point
;
4110 target_space_transform
.TransformPoint(&translated_point
);
4111 gfx::Point expected_point
= gfx::Point() - ToRoundedVector2d(scroll_delta
);
4112 EXPECT_EQ(expected_point
.ToString(), translated_point
.ToString());
4115 TEST_F(LayerTreeHostImplTest
,
4116 ExternalRootLayerScrollOffsetDelegationReflectedInNextDraw
) {
4117 TestScrollOffsetDelegate scroll_delegate
;
4118 host_impl_
->SetViewportSize(gfx::Size(10, 20));
4119 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
4120 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4121 clip_layer
->SetBounds(gfx::Size(10, 20));
4122 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
4124 // Draw first frame to clear any pending draws and check scroll.
4126 CheckLayerScrollDelta(scroll_layer
, gfx::Vector2dF(0.f
, 0.f
));
4127 EXPECT_FALSE(host_impl_
->active_tree()->needs_update_draw_properties());
4129 // Set external scroll delta on delegate and notify LayerTreeHost.
4130 gfx::ScrollOffset
scroll_offset(10.f
, 10.f
);
4131 scroll_delegate
.set_getter_return_value(scroll_offset
);
4132 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
4134 // Check scroll delta reflected in layer.
4135 LayerTreeHostImpl::FrameData frame
;
4136 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4137 host_impl_
->DrawLayers(&frame
);
4138 host_impl_
->DidDrawAllLayers(frame
);
4139 EXPECT_FALSE(frame
.has_no_damage
);
4140 CheckLayerScrollDelta(scroll_layer
, ScrollOffsetToVector2dF(scroll_offset
));
4142 host_impl_
->SetRootLayerScrollOffsetDelegate(NULL
);
4145 TEST_F(LayerTreeHostImplTest
, OverscrollRoot
) {
4146 InputHandlerScrollResult scroll_result
;
4147 SetupScrollAndContentsLayers(gfx::Size(100, 100));
4148 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4149 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4151 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4153 // In-bounds scrolling does not affect overscroll.
4154 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4155 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4156 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4157 EXPECT_TRUE(scroll_result
.did_scroll
);
4158 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4159 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4160 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4162 // Overscroll events are reflected immediately.
4163 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50));
4164 EXPECT_TRUE(scroll_result
.did_scroll
);
4165 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4166 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4167 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4168 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4169 host_impl_
->accumulated_root_overscroll());
4171 // In-bounds scrolling resets accumulated overscroll for the scrolled axes.
4172 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50));
4173 EXPECT_TRUE(scroll_result
.did_scroll
);
4174 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4175 EXPECT_EQ(gfx::Vector2dF(), scroll_result
.unused_scroll_delta
);
4176 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4177 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4178 host_impl_
->accumulated_root_overscroll());
4180 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10));
4181 EXPECT_FALSE(scroll_result
.did_scroll
);
4182 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4183 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4184 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4185 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4186 host_impl_
->accumulated_root_overscroll());
4188 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0));
4189 EXPECT_TRUE(scroll_result
.did_scroll
);
4190 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4191 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4192 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4193 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4194 host_impl_
->accumulated_root_overscroll());
4196 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0));
4197 EXPECT_TRUE(scroll_result
.did_scroll
);
4198 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4199 EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result
.unused_scroll_delta
);
4200 EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_
->accumulated_root_overscroll());
4201 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4202 host_impl_
->accumulated_root_overscroll());
4204 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60));
4205 EXPECT_TRUE(scroll_result
.did_scroll
);
4206 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4207 EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result
.unused_scroll_delta
);
4208 EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_
->accumulated_root_overscroll());
4209 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4210 host_impl_
->accumulated_root_overscroll());
4212 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60));
4213 EXPECT_TRUE(scroll_result
.did_scroll
);
4214 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4215 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4216 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4217 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4218 host_impl_
->accumulated_root_overscroll());
4220 // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long
4221 // as no scroll occurs.
4222 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4223 EXPECT_FALSE(scroll_result
.did_scroll
);
4224 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4225 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4226 EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_
->accumulated_root_overscroll());
4227 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4228 host_impl_
->accumulated_root_overscroll());
4230 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4231 EXPECT_FALSE(scroll_result
.did_scroll
);
4232 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4233 EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result
.unused_scroll_delta
);
4234 EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_
->accumulated_root_overscroll());
4235 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4236 host_impl_
->accumulated_root_overscroll());
4238 // Overscroll resets on valid scroll.
4239 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4240 EXPECT_TRUE(scroll_result
.did_scroll
);
4241 EXPECT_FALSE(scroll_result
.did_overscroll_root
);
4242 EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result
.unused_scroll_delta
);
4243 EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_
->accumulated_root_overscroll());
4244 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4245 host_impl_
->accumulated_root_overscroll());
4247 scroll_result
= host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20));
4248 EXPECT_TRUE(scroll_result
.did_scroll
);
4249 EXPECT_TRUE(scroll_result
.did_overscroll_root
);
4250 EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result
.unused_scroll_delta
);
4251 EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_
->accumulated_root_overscroll());
4252 EXPECT_EQ(scroll_result
.accumulated_root_overscroll
,
4253 host_impl_
->accumulated_root_overscroll());
4255 host_impl_
->ScrollEnd();
4259 TEST_F(LayerTreeHostImplTest
, OverscrollChildWithoutBubbling
) {
4260 // Scroll child layers beyond their maximum scroll range and make sure root
4261 // overscroll does not accumulate.
4262 gfx::Size
surface_size(10, 10);
4263 scoped_ptr
<LayerImpl
> root_clip
=
4264 LayerImpl::Create(host_impl_
->active_tree(), 4);
4265 root_clip
->SetHasRenderSurface(true);
4267 scoped_ptr
<LayerImpl
> root
=
4268 CreateScrollableLayer(1, surface_size
, root_clip
.get());
4270 scoped_ptr
<LayerImpl
> grand_child
=
4271 CreateScrollableLayer(3, surface_size
, root_clip
.get());
4273 scoped_ptr
<LayerImpl
> child
=
4274 CreateScrollableLayer(2, surface_size
, root_clip
.get());
4275 LayerImpl
* grand_child_layer
= grand_child
.get();
4276 child
->AddChild(grand_child
.Pass());
4278 LayerImpl
* child_layer
= child
.get();
4279 root
->AddChild(child
.Pass());
4280 root_clip
->AddChild(root
.Pass());
4281 child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 3));
4282 grand_child_layer
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
4283 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4284 host_impl_
->active_tree()->DidBecomeActive();
4285 host_impl_
->SetViewportSize(surface_size
);
4288 gfx::Vector2d
scroll_delta(0, -10);
4289 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4290 host_impl_
->ScrollBegin(gfx::Point(),
4291 InputHandler::NON_BUBBLING_GESTURE
));
4292 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4293 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4294 host_impl_
->ScrollEnd();
4296 // The next time we scroll we should only scroll the parent, but overscroll
4297 // should still not reach the root layer.
4298 scroll_delta
= gfx::Vector2d(0, -30);
4299 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4300 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4301 InputHandler::NON_BUBBLING_GESTURE
));
4302 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4303 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4304 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4305 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_layer
);
4306 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4307 host_impl_
->ScrollEnd();
4309 // After scrolling the parent, another scroll on the opposite direction
4310 // should scroll the child.
4311 scroll_delta
= gfx::Vector2d(0, 70);
4312 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4313 host_impl_
->ScrollBegin(gfx::Point(5, 5),
4314 InputHandler::NON_BUBBLING_GESTURE
));
4315 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4316 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4317 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child_layer
);
4318 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4319 host_impl_
->ScrollEnd();
4323 TEST_F(LayerTreeHostImplTest
, OverscrollChildEventBubbling
) {
4324 // When we try to scroll a non-scrollable child layer, the scroll delta
4325 // should be applied to one of its ancestors if possible. Overscroll should
4326 // be reflected only when it has bubbled up to the root scrolling layer.
4327 gfx::Size
surface_size(10, 10);
4328 gfx::Size
content_size(20, 20);
4329 scoped_ptr
<LayerImpl
> root_clip
=
4330 LayerImpl::Create(host_impl_
->active_tree(), 3);
4331 root_clip
->SetHasRenderSurface(true);
4333 scoped_ptr
<LayerImpl
> root
=
4334 CreateScrollableLayer(1, content_size
, root_clip
.get());
4335 root
->SetIsContainerForFixedPositionLayers(true);
4336 scoped_ptr
<LayerImpl
> child
=
4337 CreateScrollableLayer(2, content_size
, root_clip
.get());
4339 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4340 root
->AddChild(child
.Pass());
4341 root_clip
->AddChild(root
.Pass());
4343 host_impl_
->SetViewportSize(surface_size
);
4344 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4345 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4347 host_impl_
->active_tree()->DidBecomeActive();
4350 gfx::Vector2d
scroll_delta(0, 8);
4351 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4352 host_impl_
->ScrollBegin(gfx::Point(5, 5), InputHandler::WHEEL
));
4353 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4354 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4355 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4356 EXPECT_EQ(gfx::Vector2dF(0, 6), host_impl_
->accumulated_root_overscroll());
4357 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
4358 EXPECT_EQ(gfx::Vector2dF(0, 14), host_impl_
->accumulated_root_overscroll());
4359 host_impl_
->ScrollEnd();
4363 TEST_F(LayerTreeHostImplTest
, OverscrollAlways
) {
4364 LayerTreeSettings settings
;
4365 CreateHostImpl(settings
, CreateOutputSurface());
4367 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(50, 50));
4368 LayerImpl
* clip_layer
= scroll_layer
->parent()->parent();
4369 clip_layer
->SetBounds(gfx::Size(50, 50));
4370 host_impl_
->SetViewportSize(gfx::Size(50, 50));
4371 host_impl_
->active_tree()->PushPageScaleFromMainThread(1.f
, 0.5f
, 4.f
);
4373 EXPECT_EQ(gfx::Vector2dF(), host_impl_
->accumulated_root_overscroll());
4375 // Even though the layer can't scroll the overscroll still happens.
4376 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4377 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
4378 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10));
4379 EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_
->accumulated_root_overscroll());
4382 TEST_F(LayerTreeHostImplTest
, NoOverscrollOnFractionalDeviceScale
) {
4383 gfx::Size
surface_size(980, 1439);
4384 gfx::Size
content_size(980, 1438);
4385 float device_scale_factor
= 1.5f
;
4386 scoped_ptr
<LayerImpl
> root_clip
=
4387 LayerImpl::Create(host_impl_
->active_tree(), 3);
4388 root_clip
->SetHasRenderSurface(true);
4390 scoped_ptr
<LayerImpl
> root
=
4391 CreateScrollableLayer(1, content_size
, root_clip
.get());
4392 root
->SetIsContainerForFixedPositionLayers(true);
4393 scoped_ptr
<LayerImpl
> child
=
4394 CreateScrollableLayer(2, content_size
, root_clip
.get());
4395 root
->scroll_clip_layer()->SetBounds(gfx::Size(320, 469));
4396 host_impl_
->active_tree()->PushPageScaleFromMainThread(0.326531f
, 0.326531f
,
4398 host_impl_
->SetPageScaleOnActiveTree(0.326531f
);
4399 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4400 root
->AddChild(child
.Pass());
4401 root_clip
->AddChild(root
.Pass());
4403 host_impl_
->SetViewportSize(surface_size
);
4404 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
4405 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4406 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4408 host_impl_
->active_tree()->DidBecomeActive();
4411 // Horizontal & Vertical GlowEffect should not be applied when
4412 // content size is less then view port size. For Example Horizontal &
4413 // vertical GlowEffect should not be applied in about:blank page.
4414 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4415 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4416 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -1));
4417 EXPECT_EQ(gfx::Vector2dF().ToString(),
4418 host_impl_
->accumulated_root_overscroll().ToString());
4420 host_impl_
->ScrollEnd();
4424 TEST_F(LayerTreeHostImplTest
, NoOverscrollWhenNotAtEdge
) {
4425 gfx::Size
surface_size(100, 100);
4426 gfx::Size
content_size(200, 200);
4427 scoped_ptr
<LayerImpl
> root_clip
=
4428 LayerImpl::Create(host_impl_
->active_tree(), 3);
4429 root_clip
->SetHasRenderSurface(true);
4431 scoped_ptr
<LayerImpl
> root
=
4432 CreateScrollableLayer(1, content_size
, root_clip
.get());
4433 root
->SetIsContainerForFixedPositionLayers(true);
4434 scoped_ptr
<LayerImpl
> child
=
4435 CreateScrollableLayer(2, content_size
, root_clip
.get());
4437 child
->SetScrollClipLayer(Layer::INVALID_ID
);
4438 root
->AddChild(child
.Pass());
4439 root_clip
->AddChild(root
.Pass());
4441 host_impl_
->SetViewportSize(surface_size
);
4442 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
4443 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
4445 host_impl_
->active_tree()->DidBecomeActive();
4448 // Edge glow effect should be applicable only upon reaching Edges
4449 // of the content. unnecessary glow effect calls shouldn't be
4450 // called while scrolling up without reaching the edge of the content.
4451 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4452 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4453 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
4454 EXPECT_EQ(gfx::Vector2dF().ToString(),
4455 host_impl_
->accumulated_root_overscroll().ToString());
4456 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f
));
4457 EXPECT_EQ(gfx::Vector2dF().ToString(),
4458 host_impl_
->accumulated_root_overscroll().ToString());
4459 host_impl_
->ScrollEnd();
4460 // unusedrootDelta should be subtracted from applied delta so that
4461 // unwanted glow effect calls are not called.
4462 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4463 host_impl_
->ScrollBegin(gfx::Point(0, 0),
4464 InputHandler::NON_BUBBLING_GESTURE
));
4465 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
4466 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 20));
4467 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4468 host_impl_
->accumulated_root_overscroll().ToString());
4470 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(0.02f
, -0.01f
));
4471 EXPECT_EQ(gfx::Vector2dF(0.000000f
, 17.699997f
).ToString(),
4472 host_impl_
->accumulated_root_overscroll().ToString());
4473 host_impl_
->ScrollEnd();
4474 // TestCase to check kEpsilon, which prevents minute values to trigger
4475 // gloweffect without reaching edge.
4476 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
4477 host_impl_
->ScrollBegin(gfx::Point(0, 0), InputHandler::WHEEL
));
4478 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2dF(-0.12f
, 0.1f
));
4479 EXPECT_EQ(gfx::Vector2dF().ToString(),
4480 host_impl_
->accumulated_root_overscroll().ToString());
4481 host_impl_
->ScrollEnd();
4485 class BlendStateCheckLayer
: public LayerImpl
{
4487 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
,
4489 ResourceProvider
* resource_provider
) {
4490 return make_scoped_ptr(
4491 new BlendStateCheckLayer(tree_impl
, id
, resource_provider
));
4494 void AppendQuads(RenderPass
* render_pass
,
4495 AppendQuadsData
* append_quads_data
) override
{
4496 quads_appended_
= true;
4498 gfx::Rect opaque_rect
;
4499 if (contents_opaque())
4500 opaque_rect
= quad_rect_
;
4502 opaque_rect
= opaque_content_rect_
;
4503 gfx::Rect visible_quad_rect
= quad_rect_
;
4505 SharedQuadState
* shared_quad_state
=
4506 render_pass
->CreateAndAppendSharedQuadState();
4507 PopulateSharedQuadState(shared_quad_state
);
4509 TileDrawQuad
* test_blending_draw_quad
=
4510 render_pass
->CreateAndAppendDrawQuad
<TileDrawQuad
>();
4511 test_blending_draw_quad
->SetNew(shared_quad_state
,
4516 gfx::RectF(0.f
, 0.f
, 1.f
, 1.f
),
4520 test_blending_draw_quad
->visible_rect
= quad_visible_rect_
;
4521 EXPECT_EQ(blend_
, test_blending_draw_quad
->ShouldDrawWithBlending());
4522 EXPECT_EQ(has_render_surface_
, !!render_surface());
4525 void SetExpectation(bool blend
, bool has_render_surface
) {
4527 has_render_surface_
= has_render_surface
;
4528 quads_appended_
= false;
4531 bool quads_appended() const { return quads_appended_
; }
4533 void SetQuadRect(const gfx::Rect
& rect
) { quad_rect_
= rect
; }
4534 void SetQuadVisibleRect(const gfx::Rect
& rect
) { quad_visible_rect_
= rect
; }
4535 void SetOpaqueContentRect(const gfx::Rect
& rect
) {
4536 opaque_content_rect_
= rect
;
4540 BlendStateCheckLayer(LayerTreeImpl
* tree_impl
,
4542 ResourceProvider
* resource_provider
)
4543 : LayerImpl(tree_impl
, id
),
4545 has_render_surface_(false),
4546 quads_appended_(false),
4547 quad_rect_(5, 5, 5, 5),
4548 quad_visible_rect_(5, 5, 5, 5),
4549 resource_id_(resource_provider
->CreateResource(
4552 ResourceProvider::TEXTURE_HINT_IMMUTABLE
,
4554 resource_provider
->AllocateForTesting(resource_id_
);
4555 SetBounds(gfx::Size(10, 10));
4556 SetContentBounds(gfx::Size(10, 10));
4557 SetDrawsContent(true);
4561 bool has_render_surface_
;
4562 bool quads_appended_
;
4563 gfx::Rect quad_rect_
;
4564 gfx::Rect opaque_content_rect_
;
4565 gfx::Rect quad_visible_rect_
;
4566 ResourceId resource_id_
;
4569 TEST_F(LayerTreeHostImplTest
, BlendingOffWhenDrawingOpaqueLayers
) {
4571 scoped_ptr
<LayerImpl
> root
=
4572 LayerImpl::Create(host_impl_
->active_tree(), 1);
4573 root
->SetBounds(gfx::Size(10, 10));
4574 root
->SetContentBounds(root
->bounds());
4575 root
->SetDrawsContent(false);
4576 root
->SetHasRenderSurface(true);
4577 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
4579 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
4582 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4584 host_impl_
->resource_provider()));
4585 BlendStateCheckLayer
* layer1
=
4586 static_cast<BlendStateCheckLayer
*>(root
->children()[0]);
4587 layer1
->SetPosition(gfx::PointF(2.f
, 2.f
));
4589 LayerTreeHostImpl::FrameData frame
;
4591 // Opaque layer, drawn without blending.
4592 layer1
->SetContentsOpaque(true);
4593 layer1
->SetExpectation(false, false);
4594 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4595 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4596 host_impl_
->DrawLayers(&frame
);
4597 EXPECT_TRUE(layer1
->quads_appended());
4598 host_impl_
->DidDrawAllLayers(frame
);
4600 // Layer with translucent content and painting, so drawn with blending.
4601 layer1
->SetContentsOpaque(false);
4602 layer1
->SetExpectation(true, false);
4603 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4604 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4605 host_impl_
->DrawLayers(&frame
);
4606 EXPECT_TRUE(layer1
->quads_appended());
4607 host_impl_
->DidDrawAllLayers(frame
);
4609 // Layer with translucent opacity, drawn with blending.
4610 layer1
->SetContentsOpaque(true);
4611 layer1
->SetOpacity(0.5f
);
4612 layer1
->SetExpectation(true, false);
4613 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4614 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4615 host_impl_
->DrawLayers(&frame
);
4616 EXPECT_TRUE(layer1
->quads_appended());
4617 host_impl_
->DidDrawAllLayers(frame
);
4619 // Layer with translucent opacity and painting, drawn with blending.
4620 layer1
->SetContentsOpaque(true);
4621 layer1
->SetOpacity(0.5f
);
4622 layer1
->SetExpectation(true, false);
4623 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4624 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4625 host_impl_
->DrawLayers(&frame
);
4626 EXPECT_TRUE(layer1
->quads_appended());
4627 host_impl_
->DidDrawAllLayers(frame
);
4630 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4632 host_impl_
->resource_provider()));
4633 BlendStateCheckLayer
* layer2
=
4634 static_cast<BlendStateCheckLayer
*>(layer1
->children()[0]);
4635 layer2
->SetPosition(gfx::PointF(4.f
, 4.f
));
4637 // 2 opaque layers, drawn without blending.
4638 layer1
->SetContentsOpaque(true);
4639 layer1
->SetOpacity(1.f
);
4640 layer1
->SetExpectation(false, false);
4641 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4642 layer2
->SetContentsOpaque(true);
4643 layer2
->SetOpacity(1.f
);
4644 layer2
->SetExpectation(false, false);
4645 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4646 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4647 host_impl_
->DrawLayers(&frame
);
4648 EXPECT_TRUE(layer1
->quads_appended());
4649 EXPECT_TRUE(layer2
->quads_appended());
4650 host_impl_
->DidDrawAllLayers(frame
);
4652 // Parent layer with translucent content, drawn with blending.
4653 // Child layer with opaque content, drawn without blending.
4654 layer1
->SetContentsOpaque(false);
4655 layer1
->SetExpectation(true, false);
4656 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4657 layer2
->SetExpectation(false, false);
4658 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4659 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4660 host_impl_
->DrawLayers(&frame
);
4661 EXPECT_TRUE(layer1
->quads_appended());
4662 EXPECT_TRUE(layer2
->quads_appended());
4663 host_impl_
->DidDrawAllLayers(frame
);
4665 // Parent layer with translucent content but opaque painting, drawn without
4667 // Child layer with opaque content, drawn without blending.
4668 layer1
->SetContentsOpaque(true);
4669 layer1
->SetExpectation(false, false);
4670 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4671 layer2
->SetExpectation(false, false);
4672 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4673 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4674 host_impl_
->DrawLayers(&frame
);
4675 EXPECT_TRUE(layer1
->quads_appended());
4676 EXPECT_TRUE(layer2
->quads_appended());
4677 host_impl_
->DidDrawAllLayers(frame
);
4679 // Parent layer with translucent opacity and opaque content. Since it has a
4680 // drawing child, it's drawn to a render surface which carries the opacity,
4681 // so it's itself drawn without blending.
4682 // Child layer with opaque content, drawn without blending (parent surface
4683 // carries the inherited opacity).
4684 layer1
->SetContentsOpaque(true);
4685 layer1
->SetOpacity(0.5f
);
4686 layer1
->SetHasRenderSurface(true);
4687 layer1
->SetExpectation(false, true);
4688 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4689 layer2
->SetExpectation(false, false);
4690 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4691 FakeLayerTreeHostImpl::RecursiveUpdateNumChildren(
4692 host_impl_
->active_tree()->root_layer());
4693 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4694 host_impl_
->DrawLayers(&frame
);
4695 EXPECT_TRUE(layer1
->quads_appended());
4696 EXPECT_TRUE(layer2
->quads_appended());
4697 host_impl_
->DidDrawAllLayers(frame
);
4698 layer1
->SetHasRenderSurface(false);
4700 // Draw again, but with child non-opaque, to make sure
4701 // layer1 not culled.
4702 layer1
->SetContentsOpaque(true);
4703 layer1
->SetOpacity(1.f
);
4704 layer1
->SetExpectation(false, false);
4705 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4706 layer2
->SetContentsOpaque(true);
4707 layer2
->SetOpacity(0.5f
);
4708 layer2
->SetExpectation(true, false);
4709 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4710 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4711 host_impl_
->DrawLayers(&frame
);
4712 EXPECT_TRUE(layer1
->quads_appended());
4713 EXPECT_TRUE(layer2
->quads_appended());
4714 host_impl_
->DidDrawAllLayers(frame
);
4716 // A second way of making the child non-opaque.
4717 layer1
->SetContentsOpaque(true);
4718 layer1
->SetOpacity(1.f
);
4719 layer1
->SetExpectation(false, false);
4720 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4721 layer2
->SetContentsOpaque(false);
4722 layer2
->SetOpacity(1.f
);
4723 layer2
->SetExpectation(true, false);
4724 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4725 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4726 host_impl_
->DrawLayers(&frame
);
4727 EXPECT_TRUE(layer1
->quads_appended());
4728 EXPECT_TRUE(layer2
->quads_appended());
4729 host_impl_
->DidDrawAllLayers(frame
);
4731 // And when the layer says its not opaque but is painted opaque, it is not
4733 layer1
->SetContentsOpaque(true);
4734 layer1
->SetOpacity(1.f
);
4735 layer1
->SetExpectation(false, false);
4736 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4737 layer2
->SetContentsOpaque(true);
4738 layer2
->SetOpacity(1.f
);
4739 layer2
->SetExpectation(false, false);
4740 layer2
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4741 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4742 host_impl_
->DrawLayers(&frame
);
4743 EXPECT_TRUE(layer1
->quads_appended());
4744 EXPECT_TRUE(layer2
->quads_appended());
4745 host_impl_
->DidDrawAllLayers(frame
);
4747 // Layer with partially opaque contents, drawn with blending.
4748 layer1
->SetContentsOpaque(false);
4749 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4750 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 5));
4751 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4752 layer1
->SetExpectation(true, false);
4753 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4754 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4755 host_impl_
->DrawLayers(&frame
);
4756 EXPECT_TRUE(layer1
->quads_appended());
4757 host_impl_
->DidDrawAllLayers(frame
);
4759 // Layer with partially opaque contents partially culled, drawn with blending.
4760 layer1
->SetContentsOpaque(false);
4761 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4762 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 5, 2));
4763 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4764 layer1
->SetExpectation(true, false);
4765 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4766 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4767 host_impl_
->DrawLayers(&frame
);
4768 EXPECT_TRUE(layer1
->quads_appended());
4769 host_impl_
->DidDrawAllLayers(frame
);
4771 // Layer with partially opaque contents culled, drawn with blending.
4772 layer1
->SetContentsOpaque(false);
4773 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4774 layer1
->SetQuadVisibleRect(gfx::Rect(7, 5, 3, 5));
4775 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4776 layer1
->SetExpectation(true, false);
4777 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4778 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4779 host_impl_
->DrawLayers(&frame
);
4780 EXPECT_TRUE(layer1
->quads_appended());
4781 host_impl_
->DidDrawAllLayers(frame
);
4783 // Layer with partially opaque contents and translucent contents culled, drawn
4784 // without blending.
4785 layer1
->SetContentsOpaque(false);
4786 layer1
->SetQuadRect(gfx::Rect(5, 5, 5, 5));
4787 layer1
->SetQuadVisibleRect(gfx::Rect(5, 5, 2, 5));
4788 layer1
->SetOpaqueContentRect(gfx::Rect(5, 5, 2, 5));
4789 layer1
->SetExpectation(false, false);
4790 layer1
->SetUpdateRect(gfx::Rect(layer1
->content_bounds()));
4791 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4792 host_impl_
->DrawLayers(&frame
);
4793 EXPECT_TRUE(layer1
->quads_appended());
4794 host_impl_
->DidDrawAllLayers(frame
);
4797 class LayerTreeHostImplViewportCoveredTest
: public LayerTreeHostImplTest
{
4799 LayerTreeHostImplViewportCoveredTest() :
4800 gutter_quad_material_(DrawQuad::SOLID_COLOR
),
4802 did_activate_pending_tree_(false) {}
4804 scoped_ptr
<OutputSurface
> CreateFakeOutputSurface(bool always_draw
) {
4806 return FakeOutputSurface::CreateAlwaysDrawAndSwap3d();
4808 return FakeOutputSurface::Create3d();
4811 void SetupActiveTreeLayers() {
4812 host_impl_
->active_tree()->set_background_color(SK_ColorGRAY
);
4813 host_impl_
->active_tree()->SetRootLayer(
4814 LayerImpl::Create(host_impl_
->active_tree(), 1));
4815 host_impl_
->active_tree()->root_layer()->SetHasRenderSurface(true);
4816 host_impl_
->active_tree()->root_layer()->AddChild(
4817 BlendStateCheckLayer::Create(host_impl_
->active_tree(),
4819 host_impl_
->resource_provider()));
4820 child_
= static_cast<BlendStateCheckLayer
*>(
4821 host_impl_
->active_tree()->root_layer()->children()[0]);
4822 child_
->SetExpectation(false, false);
4823 child_
->SetContentsOpaque(true);
4826 // Expect no gutter rects.
4827 void TestLayerCoversFullViewport() {
4828 gfx::Rect
layer_rect(viewport_size_
);
4829 child_
->SetPosition(layer_rect
.origin());
4830 child_
->SetBounds(layer_rect
.size());
4831 child_
->SetContentBounds(layer_rect
.size());
4832 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4833 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4835 LayerTreeHostImpl::FrameData frame
;
4836 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4837 ASSERT_EQ(1u, frame
.render_passes
.size());
4839 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4840 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4841 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4843 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4844 host_impl_
->DidDrawAllLayers(frame
);
4847 // Expect fullscreen gutter rect.
4848 void TestEmptyLayer() {
4849 gfx::Rect
layer_rect(0, 0, 0, 0);
4850 child_
->SetPosition(layer_rect
.origin());
4851 child_
->SetBounds(layer_rect
.size());
4852 child_
->SetContentBounds(layer_rect
.size());
4853 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4854 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4856 LayerTreeHostImpl::FrameData frame
;
4857 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4858 ASSERT_EQ(1u, frame
.render_passes
.size());
4860 EXPECT_EQ(1u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4861 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4862 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4864 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4865 host_impl_
->DidDrawAllLayers(frame
);
4868 // Expect four surrounding gutter rects.
4869 void TestLayerInMiddleOfViewport() {
4870 gfx::Rect
layer_rect(500, 500, 200, 200);
4871 child_
->SetPosition(layer_rect
.origin());
4872 child_
->SetBounds(layer_rect
.size());
4873 child_
->SetContentBounds(layer_rect
.size());
4874 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4875 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4877 LayerTreeHostImpl::FrameData frame
;
4878 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4879 ASSERT_EQ(1u, frame
.render_passes
.size());
4881 EXPECT_EQ(4u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4882 EXPECT_EQ(5u, frame
.render_passes
[0]->quad_list
.size());
4883 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4885 VerifyQuadsExactlyCoverViewport(frame
.render_passes
[0]->quad_list
);
4886 host_impl_
->DidDrawAllLayers(frame
);
4889 // Expect no gutter rects.
4890 void TestLayerIsLargerThanViewport() {
4891 gfx::Rect
layer_rect(viewport_size_
.width() + 10,
4892 viewport_size_
.height() + 10);
4893 child_
->SetPosition(layer_rect
.origin());
4894 child_
->SetBounds(layer_rect
.size());
4895 child_
->SetContentBounds(layer_rect
.size());
4896 child_
->SetQuadRect(gfx::Rect(layer_rect
.size()));
4897 child_
->SetQuadVisibleRect(gfx::Rect(layer_rect
.size()));
4899 LayerTreeHostImpl::FrameData frame
;
4900 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
4901 ASSERT_EQ(1u, frame
.render_passes
.size());
4903 EXPECT_EQ(0u, CountGutterQuads(frame
.render_passes
[0]->quad_list
));
4904 EXPECT_EQ(1u, frame
.render_passes
[0]->quad_list
.size());
4905 ValidateTextureDrawQuads(frame
.render_passes
[0]->quad_list
);
4907 host_impl_
->DidDrawAllLayers(frame
);
4910 void DidActivateSyncTree() override
{ did_activate_pending_tree_
= true; }
4912 void set_gutter_quad_material(DrawQuad::Material material
) {
4913 gutter_quad_material_
= material
;
4915 void set_gutter_texture_size(const gfx::Size
& gutter_texture_size
) {
4916 gutter_texture_size_
= gutter_texture_size
;
4920 size_t CountGutterQuads(const QuadList
& quad_list
) {
4921 size_t num_gutter_quads
= 0;
4922 for (const auto& quad
: quad_list
) {
4923 num_gutter_quads
+= (quad
->material
== gutter_quad_material_
) ? 1 : 0;
4925 return num_gutter_quads
;
4928 void VerifyQuadsExactlyCoverViewport(const QuadList
& quad_list
) {
4929 LayerTestCommon::VerifyQuadsExactlyCoverRect(
4930 quad_list
, gfx::Rect(DipSizeToPixelSize(viewport_size_
)));
4933 // Make sure that the texture coordinates match their expectations.
4934 void ValidateTextureDrawQuads(const QuadList
& quad_list
) {
4935 for (const auto& quad
: quad_list
) {
4936 if (quad
->material
!= DrawQuad::TEXTURE_CONTENT
)
4938 const TextureDrawQuad
* texture_quad
= TextureDrawQuad::MaterialCast(quad
);
4939 gfx::SizeF gutter_texture_size_pixels
= gfx::ScaleSize(
4940 gutter_texture_size_
, host_impl_
->device_scale_factor());
4941 EXPECT_EQ(texture_quad
->uv_top_left
.x(),
4942 texture_quad
->rect
.x() / gutter_texture_size_pixels
.width());
4943 EXPECT_EQ(texture_quad
->uv_top_left
.y(),
4944 texture_quad
->rect
.y() / gutter_texture_size_pixels
.height());
4946 texture_quad
->uv_bottom_right
.x(),
4947 texture_quad
->rect
.right() / gutter_texture_size_pixels
.width());
4949 texture_quad
->uv_bottom_right
.y(),
4950 texture_quad
->rect
.bottom() / gutter_texture_size_pixels
.height());
4954 gfx::Size
DipSizeToPixelSize(const gfx::Size
& size
) {
4955 return gfx::ToRoundedSize(
4956 gfx::ScaleSize(size
, host_impl_
->device_scale_factor()));
4959 DrawQuad::Material gutter_quad_material_
;
4960 gfx::Size gutter_texture_size_
;
4961 gfx::Size viewport_size_
;
4962 BlendStateCheckLayer
* child_
;
4963 bool did_activate_pending_tree_
;
4966 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCovered
) {
4967 viewport_size_
= gfx::Size(1000, 1000);
4969 bool always_draw
= false;
4970 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4972 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4973 SetupActiveTreeLayers();
4974 TestLayerCoversFullViewport();
4976 TestLayerInMiddleOfViewport();
4977 TestLayerIsLargerThanViewport();
4980 TEST_F(LayerTreeHostImplViewportCoveredTest
, ViewportCoveredScaled
) {
4981 viewport_size_
= gfx::Size(1000, 1000);
4983 bool always_draw
= false;
4984 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
4986 host_impl_
->SetDeviceScaleFactor(2.f
);
4987 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
4988 SetupActiveTreeLayers();
4989 TestLayerCoversFullViewport();
4991 TestLayerInMiddleOfViewport();
4992 TestLayerIsLargerThanViewport();
4995 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeGrowViewportInvalid
) {
4996 viewport_size_
= gfx::Size(1000, 1000);
4998 bool always_draw
= true;
4999 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5001 // Pending tree to force active_tree size invalid. Not used otherwise.
5002 host_impl_
->CreatePendingTree();
5003 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5004 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5006 SetupActiveTreeLayers();
5008 TestLayerInMiddleOfViewport();
5009 TestLayerIsLargerThanViewport();
5012 TEST_F(LayerTreeHostImplViewportCoveredTest
, ActiveTreeShrinkViewportInvalid
) {
5013 viewport_size_
= gfx::Size(1000, 1000);
5015 bool always_draw
= true;
5016 CreateHostImpl(DefaultSettings(), CreateFakeOutputSurface(always_draw
));
5018 // Set larger viewport and activate it to active tree.
5019 host_impl_
->CreatePendingTree();
5020 gfx::Size
larger_viewport(viewport_size_
.width() + 100,
5021 viewport_size_
.height() + 100);
5022 host_impl_
->SetViewportSize(DipSizeToPixelSize(larger_viewport
));
5023 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5024 host_impl_
->ActivateSyncTree();
5025 EXPECT_TRUE(did_activate_pending_tree_
);
5026 EXPECT_FALSE(host_impl_
->active_tree()->ViewportSizeInvalid());
5028 // Shrink pending tree viewport without activating.
5029 host_impl_
->CreatePendingTree();
5030 host_impl_
->SetViewportSize(DipSizeToPixelSize(viewport_size_
));
5031 EXPECT_TRUE(host_impl_
->active_tree()->ViewportSizeInvalid());
5033 SetupActiveTreeLayers();
5035 TestLayerInMiddleOfViewport();
5036 TestLayerIsLargerThanViewport();
5039 class FakeDrawableLayerImpl
: public LayerImpl
{
5041 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5042 return make_scoped_ptr(new FakeDrawableLayerImpl(tree_impl
, id
));
5045 FakeDrawableLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5046 : LayerImpl(tree_impl
, id
) {}
5049 // Only reshape when we know we are going to draw. Otherwise, the reshape
5050 // can leave the window at the wrong size if we never draw and the proper
5051 // viewport size is never set.
5052 TEST_F(LayerTreeHostImplTest
, ReshapeNotCalledUntilDraw
) {
5053 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5054 scoped_ptr
<OutputSurface
> output_surface(
5055 FakeOutputSurface::Create3d(provider
));
5056 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5058 scoped_ptr
<LayerImpl
> root
=
5059 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5060 root
->SetBounds(gfx::Size(10, 10));
5061 root
->SetContentBounds(gfx::Size(10, 10));
5062 root
->SetDrawsContent(true);
5063 root
->SetHasRenderSurface(true);
5064 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5065 EXPECT_FALSE(provider
->TestContext3d()->reshape_called());
5066 provider
->TestContext3d()->clear_reshape_called();
5068 LayerTreeHostImpl::FrameData frame
;
5069 host_impl_
->SetViewportSize(gfx::Size(10, 10));
5070 host_impl_
->SetDeviceScaleFactor(1.f
);
5071 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5072 host_impl_
->DrawLayers(&frame
);
5073 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5074 EXPECT_EQ(provider
->TestContext3d()->width(), 10);
5075 EXPECT_EQ(provider
->TestContext3d()->height(), 10);
5076 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5077 host_impl_
->DidDrawAllLayers(frame
);
5078 provider
->TestContext3d()->clear_reshape_called();
5080 host_impl_
->SetViewportSize(gfx::Size(20, 30));
5081 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5082 host_impl_
->DrawLayers(&frame
);
5083 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5084 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5085 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5086 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 1.f
);
5087 host_impl_
->DidDrawAllLayers(frame
);
5088 provider
->TestContext3d()->clear_reshape_called();
5090 host_impl_
->SetDeviceScaleFactor(2.f
);
5091 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5092 host_impl_
->DrawLayers(&frame
);
5093 EXPECT_TRUE(provider
->TestContext3d()->reshape_called());
5094 EXPECT_EQ(provider
->TestContext3d()->width(), 20);
5095 EXPECT_EQ(provider
->TestContext3d()->height(), 30);
5096 EXPECT_EQ(provider
->TestContext3d()->scale_factor(), 2.f
);
5097 host_impl_
->DidDrawAllLayers(frame
);
5098 provider
->TestContext3d()->clear_reshape_called();
5101 // Make sure damage tracking propagates all the way to the graphics context,
5102 // where it should request to swap only the sub-buffer that is damaged.
5103 TEST_F(LayerTreeHostImplTest
, PartialSwapReceivesDamageRect
) {
5104 scoped_refptr
<TestContextProvider
> context_provider(
5105 TestContextProvider::Create());
5106 context_provider
->BindToCurrentThread();
5107 context_provider
->TestContext3d()->set_have_post_sub_buffer(true);
5109 scoped_ptr
<FakeOutputSurface
> output_surface(
5110 FakeOutputSurface::Create3d(context_provider
));
5111 FakeOutputSurface
* fake_output_surface
= output_surface
.get();
5113 // This test creates its own LayerTreeHostImpl, so
5114 // that we can force partial swap enabled.
5115 LayerTreeSettings settings
;
5116 settings
.renderer_settings
.partial_swap_enabled
= true;
5117 scoped_ptr
<LayerTreeHostImpl
> layer_tree_host_impl
=
5118 LayerTreeHostImpl::Create(
5119 settings
, this, &proxy_
, &stats_instrumentation_
,
5120 shared_bitmap_manager_
.get(), NULL
, task_graph_runner_
.get(), 0);
5121 layer_tree_host_impl
->InitializeRenderer(output_surface
.Pass());
5122 layer_tree_host_impl
->WillBeginImplFrame(
5123 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5124 layer_tree_host_impl
->SetViewportSize(gfx::Size(500, 500));
5126 scoped_ptr
<LayerImpl
> root
=
5127 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 1);
5128 root
->SetHasRenderSurface(true);
5129 scoped_ptr
<LayerImpl
> child
=
5130 FakeDrawableLayerImpl::Create(layer_tree_host_impl
->active_tree(), 2);
5131 child
->SetPosition(gfx::PointF(12.f
, 13.f
));
5132 child
->SetBounds(gfx::Size(14, 15));
5133 child
->SetContentBounds(gfx::Size(14, 15));
5134 child
->SetDrawsContent(true);
5135 root
->SetBounds(gfx::Size(500, 500));
5136 root
->SetContentBounds(gfx::Size(500, 500));
5137 root
->SetDrawsContent(true);
5138 root
->AddChild(child
.Pass());
5139 layer_tree_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5141 LayerTreeHostImpl::FrameData frame
;
5143 // First frame, the entire screen should get swapped.
5144 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5145 layer_tree_host_impl
->DrawLayers(&frame
);
5146 layer_tree_host_impl
->DidDrawAllLayers(frame
);
5147 layer_tree_host_impl
->SwapBuffers(frame
);
5148 gfx::Rect
expected_swap_rect(0, 0, 500, 500);
5149 EXPECT_EQ(expected_swap_rect
.ToString(),
5150 fake_output_surface
->last_swap_rect().ToString());
5152 // Second frame, only the damaged area should get swapped. Damage should be
5153 // the union of old and new child rects.
5154 // expected damage rect: gfx::Rect(26, 28);
5155 // expected swap rect: vertically flipped, with origin at bottom left corner.
5156 layer_tree_host_impl
->active_tree()->root_layer()->children()[0]->SetPosition(
5158 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5159 layer_tree_host_impl
->DrawLayers(&frame
);
5160 host_impl_
->DidDrawAllLayers(frame
);
5161 layer_tree_host_impl
->SwapBuffers(frame
);
5163 // Make sure that partial swap is constrained to the viewport dimensions
5164 // expected damage rect: gfx::Rect(500, 500);
5165 // expected swap rect: flipped damage rect, but also clamped to viewport
5166 expected_swap_rect
= gfx::Rect(0, 500-28, 26, 28);
5167 EXPECT_EQ(expected_swap_rect
.ToString(),
5168 fake_output_surface
->last_swap_rect().ToString());
5170 layer_tree_host_impl
->SetViewportSize(gfx::Size(10, 10));
5171 // This will damage everything.
5172 layer_tree_host_impl
->active_tree()->root_layer()->SetBackgroundColor(
5174 EXPECT_EQ(DRAW_SUCCESS
, layer_tree_host_impl
->PrepareToDraw(&frame
));
5175 layer_tree_host_impl
->DrawLayers(&frame
);
5176 host_impl_
->DidDrawAllLayers(frame
);
5177 layer_tree_host_impl
->SwapBuffers(frame
);
5179 expected_swap_rect
= gfx::Rect(0, 0, 10, 10);
5180 EXPECT_EQ(expected_swap_rect
.ToString(),
5181 fake_output_surface
->last_swap_rect().ToString());
5184 TEST_F(LayerTreeHostImplTest
, RootLayerDoesntCreateExtraSurface
) {
5185 scoped_ptr
<LayerImpl
> root
=
5186 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 1);
5187 scoped_ptr
<LayerImpl
> child
=
5188 FakeDrawableLayerImpl::Create(host_impl_
->active_tree(), 2);
5189 child
->SetBounds(gfx::Size(10, 10));
5190 child
->SetContentBounds(gfx::Size(10, 10));
5191 child
->SetDrawsContent(true);
5192 root
->SetBounds(gfx::Size(10, 10));
5193 root
->SetContentBounds(gfx::Size(10, 10));
5194 root
->SetDrawsContent(true);
5195 root
->SetHasRenderSurface(true);
5196 root
->AddChild(child
.Pass());
5198 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5200 LayerTreeHostImpl::FrameData frame
;
5202 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5203 EXPECT_EQ(1u, frame
.render_surface_layer_list
->size());
5204 EXPECT_EQ(1u, frame
.render_passes
.size());
5205 host_impl_
->DidDrawAllLayers(frame
);
5208 class FakeLayerWithQuads
: public LayerImpl
{
5210 static scoped_ptr
<LayerImpl
> Create(LayerTreeImpl
* tree_impl
, int id
) {
5211 return make_scoped_ptr(new FakeLayerWithQuads(tree_impl
, id
));
5214 void AppendQuads(RenderPass
* render_pass
,
5215 AppendQuadsData
* append_quads_data
) override
{
5216 SharedQuadState
* shared_quad_state
=
5217 render_pass
->CreateAndAppendSharedQuadState();
5218 PopulateSharedQuadState(shared_quad_state
);
5220 SkColor gray
= SkColorSetRGB(100, 100, 100);
5221 gfx::Rect
quad_rect(content_bounds());
5222 gfx::Rect
visible_quad_rect(quad_rect
);
5223 SolidColorDrawQuad
* my_quad
=
5224 render_pass
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
5226 shared_quad_state
, quad_rect
, visible_quad_rect
, gray
, false);
5230 FakeLayerWithQuads(LayerTreeImpl
* tree_impl
, int id
)
5231 : LayerImpl(tree_impl
, id
) {}
5234 class MockContext
: public TestWebGraphicsContext3D
{
5236 MOCK_METHOD1(useProgram
, void(GLuint program
));
5237 MOCK_METHOD5(uniform4f
, void(GLint location
,
5242 MOCK_METHOD4(uniformMatrix4fv
, void(GLint location
,
5244 GLboolean transpose
,
5245 const GLfloat
* value
));
5246 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5250 MOCK_METHOD1(enable
, void(GLenum cap
));
5251 MOCK_METHOD1(disable
, void(GLenum cap
));
5252 MOCK_METHOD4(scissor
, void(GLint x
,
5258 class MockContextHarness
{
5260 MockContext
* context_
;
5263 explicit MockContextHarness(MockContext
* context
)
5264 : context_(context
) {
5265 context_
->set_have_post_sub_buffer(true);
5267 // Catch "uninteresting" calls
5268 EXPECT_CALL(*context_
, useProgram(_
))
5271 EXPECT_CALL(*context_
, drawElements(_
, _
, _
, _
))
5274 // These are not asserted
5275 EXPECT_CALL(*context_
, uniformMatrix4fv(_
, _
, _
, _
))
5276 .WillRepeatedly(Return());
5278 EXPECT_CALL(*context_
, uniform4f(_
, _
, _
, _
, _
))
5279 .WillRepeatedly(Return());
5281 // Any un-sanctioned calls to enable() are OK
5282 EXPECT_CALL(*context_
, enable(_
))
5283 .WillRepeatedly(Return());
5285 // Any un-sanctioned calls to disable() are OK
5286 EXPECT_CALL(*context_
, disable(_
))
5287 .WillRepeatedly(Return());
5290 void MustDrawSolidQuad() {
5291 EXPECT_CALL(*context_
, drawElements(GL_TRIANGLES
, 6, GL_UNSIGNED_SHORT
, 0))
5293 .RetiresOnSaturation();
5295 EXPECT_CALL(*context_
, useProgram(_
))
5297 .RetiresOnSaturation();
5300 void MustSetScissor(int x
, int y
, int width
, int height
) {
5301 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5302 .WillRepeatedly(Return());
5304 EXPECT_CALL(*context_
, scissor(x
, y
, width
, height
))
5306 .WillRepeatedly(Return());
5309 void MustSetNoScissor() {
5310 EXPECT_CALL(*context_
, disable(GL_SCISSOR_TEST
))
5311 .WillRepeatedly(Return());
5313 EXPECT_CALL(*context_
, enable(GL_SCISSOR_TEST
))
5316 EXPECT_CALL(*context_
, scissor(_
, _
, _
, _
))
5321 TEST_F(LayerTreeHostImplTest
, NoPartialSwap
) {
5322 scoped_ptr
<MockContext
> mock_context_owned(new MockContext
);
5323 MockContext
* mock_context
= mock_context_owned
.get();
5324 MockContextHarness
harness(mock_context
);
5327 LayerTreeSettings settings
= DefaultSettings();
5328 settings
.renderer_settings
.partial_swap_enabled
= false;
5329 CreateHostImpl(settings
,
5330 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5331 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5333 // Without partial swap, and no clipping, no scissor is set.
5334 harness
.MustDrawSolidQuad();
5335 harness
.MustSetNoScissor();
5337 LayerTreeHostImpl::FrameData frame
;
5338 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5339 host_impl_
->DrawLayers(&frame
);
5340 host_impl_
->DidDrawAllLayers(frame
);
5342 Mock::VerifyAndClearExpectations(&mock_context
);
5344 // Without partial swap, but a layer does clip its subtree, one scissor is
5346 host_impl_
->active_tree()->root_layer()->SetMasksToBounds(true);
5347 harness
.MustDrawSolidQuad();
5348 harness
.MustSetScissor(0, 0, 10, 10);
5350 LayerTreeHostImpl::FrameData frame
;
5351 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5352 host_impl_
->DrawLayers(&frame
);
5353 host_impl_
->DidDrawAllLayers(frame
);
5355 Mock::VerifyAndClearExpectations(&mock_context
);
5358 TEST_F(LayerTreeHostImplTest
, PartialSwap
) {
5359 scoped_ptr
<MockContext
> context_owned(new MockContext
);
5360 MockContext
* mock_context
= context_owned
.get();
5361 MockContextHarness
harness(mock_context
);
5363 LayerTreeSettings settings
= DefaultSettings();
5364 settings
.renderer_settings
.partial_swap_enabled
= true;
5365 CreateHostImpl(settings
, FakeOutputSurface::Create3d(context_owned
.Pass()));
5366 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5368 // The first frame is not a partially-swapped one. No scissor should be set.
5369 harness
.MustSetNoScissor();
5370 harness
.MustDrawSolidQuad();
5372 LayerTreeHostImpl::FrameData frame
;
5373 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5374 host_impl_
->DrawLayers(&frame
);
5375 host_impl_
->DidDrawAllLayers(frame
);
5377 Mock::VerifyAndClearExpectations(&mock_context
);
5379 // Damage a portion of the frame.
5380 host_impl_
->active_tree()->root_layer()->SetUpdateRect(
5381 gfx::Rect(0, 0, 2, 3));
5383 // The second frame will be partially-swapped (the y coordinates are flipped).
5384 harness
.MustSetScissor(0, 7, 2, 3);
5385 harness
.MustDrawSolidQuad();
5387 LayerTreeHostImpl::FrameData frame
;
5388 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5389 host_impl_
->DrawLayers(&frame
);
5390 host_impl_
->DidDrawAllLayers(frame
);
5392 Mock::VerifyAndClearExpectations(&mock_context
);
5395 static scoped_ptr
<LayerTreeHostImpl
> SetupLayersForOpacity(
5397 LayerTreeHostImplClient
* client
,
5399 SharedBitmapManager
* manager
,
5400 RenderingStatsInstrumentation
* stats_instrumentation
) {
5401 scoped_refptr
<TestContextProvider
> provider(TestContextProvider::Create());
5402 scoped_ptr
<OutputSurface
> output_surface(
5403 FakeOutputSurface::Create3d(provider
));
5404 provider
->BindToCurrentThread();
5405 provider
->TestContext3d()->set_have_post_sub_buffer(true);
5407 LayerTreeSettings settings
;
5408 settings
.renderer_settings
.partial_swap_enabled
= partial_swap
;
5409 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
= LayerTreeHostImpl::Create(
5410 settings
, client
, proxy
, stats_instrumentation
, manager
, NULL
, NULL
, 0);
5411 my_host_impl
->InitializeRenderer(output_surface
.Pass());
5412 my_host_impl
->WillBeginImplFrame(
5413 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
));
5414 my_host_impl
->SetViewportSize(gfx::Size(100, 100));
5417 Layers are created as follows:
5419 +--------------------+
5423 | | +-------------------+
5425 | | +-------------------+
5430 +--------------------+
5432 Layers 1, 2 have render surfaces
5434 scoped_ptr
<LayerImpl
> root
=
5435 LayerImpl::Create(my_host_impl
->active_tree(), 1);
5436 scoped_ptr
<LayerImpl
> child
=
5437 LayerImpl::Create(my_host_impl
->active_tree(), 2);
5438 scoped_ptr
<LayerImpl
> grand_child
=
5439 FakeLayerWithQuads::Create(my_host_impl
->active_tree(), 3);
5441 gfx::Rect
root_rect(0, 0, 100, 100);
5442 gfx::Rect
child_rect(10, 10, 50, 50);
5443 gfx::Rect
grand_child_rect(5, 5, 150, 150);
5445 root
->SetHasRenderSurface(true);
5446 root
->SetPosition(root_rect
.origin());
5447 root
->SetBounds(root_rect
.size());
5448 root
->SetContentBounds(root
->bounds());
5449 root
->draw_properties().visible_content_rect
= root_rect
;
5450 root
->SetDrawsContent(false);
5451 root
->render_surface()->SetContentRect(gfx::Rect(root_rect
.size()));
5453 child
->SetPosition(gfx::PointF(child_rect
.x(), child_rect
.y()));
5454 child
->SetOpacity(0.5f
);
5455 child
->SetBounds(gfx::Size(child_rect
.width(), child_rect
.height()));
5456 child
->SetContentBounds(child
->bounds());
5457 child
->draw_properties().visible_content_rect
= child_rect
;
5458 child
->SetDrawsContent(false);
5459 child
->SetHasRenderSurface(true);
5461 grand_child
->SetPosition(grand_child_rect
.origin());
5462 grand_child
->SetBounds(grand_child_rect
.size());
5463 grand_child
->SetContentBounds(grand_child
->bounds());
5464 grand_child
->draw_properties().visible_content_rect
= grand_child_rect
;
5465 grand_child
->SetDrawsContent(true);
5467 child
->AddChild(grand_child
.Pass());
5468 root
->AddChild(child
.Pass());
5470 my_host_impl
->active_tree()->SetRootLayer(root
.Pass());
5471 return my_host_impl
.Pass();
5474 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorPartialSwap
) {
5475 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
5476 new TestSharedBitmapManager());
5477 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5478 SetupLayersForOpacity(true,
5481 shared_bitmap_manager
.get(),
5482 &stats_instrumentation_
);
5484 LayerTreeHostImpl::FrameData frame
;
5485 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5487 // Verify all quads have been computed
5488 ASSERT_EQ(2U, frame
.render_passes
.size());
5489 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5490 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5491 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5492 frame
.render_passes
[0]->quad_list
.front()->material
);
5493 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5494 frame
.render_passes
[1]->quad_list
.front()->material
);
5496 my_host_impl
->DrawLayers(&frame
);
5497 my_host_impl
->DidDrawAllLayers(frame
);
5501 TEST_F(LayerTreeHostImplTest
, ContributingLayerEmptyScissorNoPartialSwap
) {
5502 scoped_ptr
<SharedBitmapManager
> shared_bitmap_manager(
5503 new TestSharedBitmapManager());
5504 scoped_ptr
<LayerTreeHostImpl
> my_host_impl
=
5505 SetupLayersForOpacity(false,
5508 shared_bitmap_manager
.get(),
5509 &stats_instrumentation_
);
5511 LayerTreeHostImpl::FrameData frame
;
5512 EXPECT_EQ(DRAW_SUCCESS
, my_host_impl
->PrepareToDraw(&frame
));
5514 // Verify all quads have been computed
5515 ASSERT_EQ(2U, frame
.render_passes
.size());
5516 ASSERT_EQ(1U, frame
.render_passes
[0]->quad_list
.size());
5517 ASSERT_EQ(1U, frame
.render_passes
[1]->quad_list
.size());
5518 EXPECT_EQ(DrawQuad::SOLID_COLOR
,
5519 frame
.render_passes
[0]->quad_list
.front()->material
);
5520 EXPECT_EQ(DrawQuad::RENDER_PASS
,
5521 frame
.render_passes
[1]->quad_list
.front()->material
);
5523 my_host_impl
->DrawLayers(&frame
);
5524 my_host_impl
->DidDrawAllLayers(frame
);
5528 TEST_F(LayerTreeHostImplTest
, LayersFreeTextures
) {
5529 scoped_ptr
<TestWebGraphicsContext3D
> context
=
5530 TestWebGraphicsContext3D::Create();
5531 TestWebGraphicsContext3D
* context3d
= context
.get();
5532 scoped_ptr
<OutputSurface
> output_surface(
5533 FakeOutputSurface::Create3d(context
.Pass()));
5534 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
5536 scoped_ptr
<LayerImpl
> root_layer
=
5537 LayerImpl::Create(host_impl_
->active_tree(), 1);
5538 root_layer
->SetBounds(gfx::Size(10, 10));
5539 root_layer
->SetHasRenderSurface(true);
5541 scoped_refptr
<VideoFrame
> softwareFrame
=
5542 media::VideoFrame::CreateColorFrame(
5543 gfx::Size(4, 4), 0x80, 0x80, 0x80, base::TimeDelta());
5544 FakeVideoFrameProvider provider
;
5545 provider
.set_frame(softwareFrame
);
5546 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5547 host_impl_
->active_tree(), 4, &provider
, media::VIDEO_ROTATION_0
);
5548 video_layer
->SetBounds(gfx::Size(10, 10));
5549 video_layer
->SetContentBounds(gfx::Size(10, 10));
5550 video_layer
->SetDrawsContent(true);
5551 root_layer
->AddChild(video_layer
.Pass());
5553 scoped_ptr
<IOSurfaceLayerImpl
> io_surface_layer
=
5554 IOSurfaceLayerImpl::Create(host_impl_
->active_tree(), 5);
5555 io_surface_layer
->SetBounds(gfx::Size(10, 10));
5556 io_surface_layer
->SetContentBounds(gfx::Size(10, 10));
5557 io_surface_layer
->SetDrawsContent(true);
5558 io_surface_layer
->SetIOSurfaceProperties(1, gfx::Size(10, 10));
5559 root_layer
->AddChild(io_surface_layer
.Pass());
5561 host_impl_
->active_tree()->SetRootLayer(root_layer
.Pass());
5563 EXPECT_EQ(0u, context3d
->NumTextures());
5565 LayerTreeHostImpl::FrameData frame
;
5566 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5567 host_impl_
->DrawLayers(&frame
);
5568 host_impl_
->DidDrawAllLayers(frame
);
5569 host_impl_
->SwapBuffers(frame
);
5571 EXPECT_GT(context3d
->NumTextures(), 0u);
5573 // Kill the layer tree.
5574 host_impl_
->active_tree()->SetRootLayer(
5575 LayerImpl::Create(host_impl_
->active_tree(), 100));
5576 // There should be no textures left in use after.
5577 EXPECT_EQ(0u, context3d
->NumTextures());
5580 class MockDrawQuadsToFillScreenContext
: public TestWebGraphicsContext3D
{
5582 MOCK_METHOD1(useProgram
, void(GLuint program
));
5583 MOCK_METHOD4(drawElements
, void(GLenum mode
,
5589 TEST_F(LayerTreeHostImplTest
, HasTransparentBackground
) {
5590 scoped_ptr
<MockDrawQuadsToFillScreenContext
> mock_context_owned(
5591 new MockDrawQuadsToFillScreenContext
);
5592 MockDrawQuadsToFillScreenContext
* mock_context
= mock_context_owned
.get();
5595 LayerTreeSettings settings
= DefaultSettings();
5596 settings
.renderer_settings
.partial_swap_enabled
= false;
5597 CreateHostImpl(settings
,
5598 FakeOutputSurface::Create3d(mock_context_owned
.Pass()));
5599 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
5600 host_impl_
->active_tree()->set_background_color(SK_ColorWHITE
);
5602 // Verify one quad is drawn when transparent background set is not set.
5603 host_impl_
->active_tree()->set_has_transparent_background(false);
5604 EXPECT_CALL(*mock_context
, useProgram(_
))
5606 EXPECT_CALL(*mock_context
, drawElements(_
, _
, _
, _
))
5608 LayerTreeHostImpl::FrameData frame
;
5609 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5610 host_impl_
->DrawLayers(&frame
);
5611 host_impl_
->DidDrawAllLayers(frame
);
5612 Mock::VerifyAndClearExpectations(&mock_context
);
5614 // Verify no quads are drawn when transparent background is set.
5615 host_impl_
->active_tree()->set_has_transparent_background(true);
5616 host_impl_
->SetFullRootLayerDamage();
5617 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5618 host_impl_
->DrawLayers(&frame
);
5619 host_impl_
->DidDrawAllLayers(frame
);
5620 Mock::VerifyAndClearExpectations(&mock_context
);
5623 TEST_F(LayerTreeHostImplTest
, ReleaseContentsTextureShouldTriggerCommit
) {
5624 set_reduce_memory_result(false);
5626 // If changing the memory limit wouldn't result in changing what was
5627 // committed, then no commit should be requested.
5628 set_reduce_memory_result(false);
5629 host_impl_
->set_max_memory_needed_bytes(
5630 host_impl_
->memory_allocation_limit_bytes() - 1);
5631 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5632 host_impl_
->memory_allocation_limit_bytes() - 1));
5633 EXPECT_FALSE(did_request_commit_
);
5634 did_request_commit_
= false;
5636 // If changing the memory limit would result in changing what was
5637 // committed, then a commit should be requested, even though nothing was
5639 set_reduce_memory_result(false);
5640 host_impl_
->set_max_memory_needed_bytes(
5641 host_impl_
->memory_allocation_limit_bytes());
5642 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5643 host_impl_
->memory_allocation_limit_bytes() - 1));
5644 EXPECT_TRUE(did_request_commit_
);
5645 did_request_commit_
= false;
5647 // Especially if changing the memory limit caused evictions, we need
5649 set_reduce_memory_result(true);
5650 host_impl_
->set_max_memory_needed_bytes(1);
5651 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5652 host_impl_
->memory_allocation_limit_bytes() - 1));
5653 EXPECT_TRUE(did_request_commit_
);
5654 did_request_commit_
= false;
5656 // But if we set it to the same value that it was before, we shouldn't
5658 host_impl_
->SetMemoryPolicy(ManagedMemoryPolicy(
5659 host_impl_
->memory_allocation_limit_bytes()));
5660 EXPECT_FALSE(did_request_commit_
);
5663 class LayerTreeHostImplTestWithDelegatingRenderer
5664 : public LayerTreeHostImplTest
{
5666 scoped_ptr
<OutputSurface
> CreateOutputSurface() override
{
5667 return FakeOutputSurface::CreateDelegating3d();
5670 void DrawFrameAndTestDamage(const gfx::RectF
& expected_damage
) {
5671 bool expect_to_draw
= !expected_damage
.IsEmpty();
5673 LayerTreeHostImpl::FrameData frame
;
5674 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5676 if (!expect_to_draw
) {
5677 // With no damage, we don't draw, and no quads are created.
5678 ASSERT_EQ(0u, frame
.render_passes
.size());
5680 ASSERT_EQ(1u, frame
.render_passes
.size());
5682 // Verify the damage rect for the root render pass.
5683 const RenderPass
* root_render_pass
= frame
.render_passes
.back();
5684 EXPECT_EQ(expected_damage
, root_render_pass
->damage_rect
);
5686 // Verify the root and child layers' quads are generated and not being
5688 ASSERT_EQ(2u, root_render_pass
->quad_list
.size());
5690 LayerImpl
* child
= host_impl_
->active_tree()->root_layer()->children()[0];
5691 gfx::RectF
expected_child_visible_rect(child
->content_bounds());
5692 EXPECT_EQ(expected_child_visible_rect
,
5693 root_render_pass
->quad_list
.front()->visible_rect
);
5695 LayerImpl
* root
= host_impl_
->active_tree()->root_layer();
5696 gfx::RectF
expected_root_visible_rect(root
->content_bounds());
5697 EXPECT_EQ(expected_root_visible_rect
,
5698 root_render_pass
->quad_list
.ElementAt(1)->visible_rect
);
5701 host_impl_
->DrawLayers(&frame
);
5702 host_impl_
->DidDrawAllLayers(frame
);
5703 EXPECT_EQ(expect_to_draw
, host_impl_
->SwapBuffers(frame
));
5707 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, FrameIncludesDamageRect
) {
5708 scoped_ptr
<SolidColorLayerImpl
> root
=
5709 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5710 root
->SetPosition(gfx::PointF());
5711 root
->SetBounds(gfx::Size(10, 10));
5712 root
->SetContentBounds(gfx::Size(10, 10));
5713 root
->SetDrawsContent(true);
5714 root
->SetHasRenderSurface(true);
5716 // Child layer is in the bottom right corner.
5717 scoped_ptr
<SolidColorLayerImpl
> child
=
5718 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 2);
5719 child
->SetPosition(gfx::PointF(9.f
, 9.f
));
5720 child
->SetBounds(gfx::Size(1, 1));
5721 child
->SetContentBounds(gfx::Size(1, 1));
5722 child
->SetDrawsContent(true);
5723 root
->AddChild(child
.Pass());
5725 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
5727 // Draw a frame. In the first frame, the entire viewport should be damaged.
5728 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
5729 DrawFrameAndTestDamage(full_frame_damage
);
5731 // The second frame has damage that doesn't touch the child layer. Its quads
5732 // should still be generated.
5733 gfx::Rect small_damage
= gfx::Rect(0, 0, 1, 1);
5734 host_impl_
->active_tree()->root_layer()->SetUpdateRect(small_damage
);
5735 DrawFrameAndTestDamage(small_damage
);
5737 // The third frame should have no damage, so no quads should be generated.
5738 gfx::Rect no_damage
;
5739 DrawFrameAndTestDamage(no_damage
);
5742 // TODO(reveman): Remove this test and the ability to prevent on demand raster
5743 // when delegating renderer supports PictureDrawQuads. crbug.com/342121
5744 TEST_F(LayerTreeHostImplTestWithDelegatingRenderer
, PreventRasterizeOnDemand
) {
5745 LayerTreeSettings settings
;
5746 CreateHostImpl(settings
, CreateOutputSurface());
5747 EXPECT_FALSE(host_impl_
->GetRendererCapabilities().allow_rasterize_on_demand
);
5750 class FakeMaskLayerImpl
: public LayerImpl
{
5752 static scoped_ptr
<FakeMaskLayerImpl
> Create(LayerTreeImpl
* tree_impl
,
5754 return make_scoped_ptr(new FakeMaskLayerImpl(tree_impl
, id
));
5757 void GetContentsResourceId(ResourceId
* resource_id
,
5758 gfx::Size
* resource_size
) const override
{
5763 FakeMaskLayerImpl(LayerTreeImpl
* tree_impl
, int id
)
5764 : LayerImpl(tree_impl
, id
) {}
5767 class GLRendererWithSetupQuadForAntialiasing
: public GLRenderer
{
5769 using GLRenderer::ShouldAntialiasQuad
;
5772 TEST_F(LayerTreeHostImplTest
, FarAwayQuadsDontNeedAA
) {
5773 // Due to precision issues (especially on Android), sometimes far
5774 // away quads can end up thinking they need AA.
5775 float device_scale_factor
= 4.f
/ 3.f
;
5776 host_impl_
->SetDeviceScaleFactor(device_scale_factor
);
5777 gfx::Size
root_size(2000, 1000);
5778 gfx::Size device_viewport_size
=
5779 gfx::ToCeiledSize(gfx::ScaleSize(root_size
, device_scale_factor
));
5780 host_impl_
->SetViewportSize(device_viewport_size
);
5782 host_impl_
->CreatePendingTree();
5783 host_impl_
->pending_tree()->PushPageScaleFromMainThread(1.f
, 1.f
/ 16.f
,
5786 scoped_ptr
<LayerImpl
> scoped_root
=
5787 LayerImpl::Create(host_impl_
->pending_tree(), 1);
5788 LayerImpl
* root
= scoped_root
.get();
5789 root
->SetHasRenderSurface(true);
5791 host_impl_
->pending_tree()->SetRootLayer(scoped_root
.Pass());
5793 scoped_ptr
<LayerImpl
> scoped_scrolling_layer
=
5794 LayerImpl::Create(host_impl_
->pending_tree(), 2);
5795 LayerImpl
* scrolling_layer
= scoped_scrolling_layer
.get();
5796 root
->AddChild(scoped_scrolling_layer
.Pass());
5798 gfx::Size
content_layer_bounds(100000, 100);
5799 gfx::Size
pile_tile_size(3000, 3000);
5800 scoped_refptr
<FakePicturePileImpl
> pile(FakePicturePileImpl::CreateFilledPile(
5801 pile_tile_size
, content_layer_bounds
));
5803 scoped_ptr
<FakePictureLayerImpl
> scoped_content_layer
=
5804 FakePictureLayerImpl::CreateWithRasterSource(host_impl_
->pending_tree(),
5806 LayerImpl
* content_layer
= scoped_content_layer
.get();
5807 scrolling_layer
->AddChild(scoped_content_layer
.Pass());
5808 content_layer
->SetBounds(content_layer_bounds
);
5809 content_layer
->SetDrawsContent(true);
5811 root
->SetBounds(root_size
);
5813 gfx::ScrollOffset
scroll_offset(100000, 0);
5814 scrolling_layer
->SetScrollClipLayer(root
->id());
5815 scrolling_layer
->PushScrollOffsetFromMainThread(scroll_offset
);
5817 host_impl_
->ActivateSyncTree();
5819 bool update_lcd_text
= false;
5820 host_impl_
->active_tree()->UpdateDrawProperties(update_lcd_text
);
5821 ASSERT_EQ(1u, host_impl_
->active_tree()->RenderSurfaceLayerList().size());
5823 LayerTreeHostImpl::FrameData frame
;
5824 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5826 ASSERT_EQ(1u, frame
.render_passes
.size());
5827 ASSERT_LE(1u, frame
.render_passes
[0]->quad_list
.size());
5828 const DrawQuad
* quad
= frame
.render_passes
[0]->quad_list
.front();
5831 GLRendererWithSetupQuadForAntialiasing::ShouldAntialiasQuad(
5832 quad
->quadTransform(), quad
, false);
5833 EXPECT_FALSE(antialiased
);
5835 host_impl_
->DrawLayers(&frame
);
5836 host_impl_
->DidDrawAllLayers(frame
);
5840 class CompositorFrameMetadataTest
: public LayerTreeHostImplTest
{
5842 CompositorFrameMetadataTest()
5843 : swap_buffers_complete_(0) {}
5845 void DidSwapBuffersCompleteOnImplThread() override
{
5846 swap_buffers_complete_
++;
5849 int swap_buffers_complete_
;
5852 TEST_F(CompositorFrameMetadataTest
, CompositorFrameAckCountsAsSwapComplete
) {
5853 SetupRootLayerImpl(FakeLayerWithQuads::Create(host_impl_
->active_tree(), 1));
5855 LayerTreeHostImpl::FrameData frame
;
5856 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5857 host_impl_
->DrawLayers(&frame
);
5858 host_impl_
->DidDrawAllLayers(frame
);
5860 CompositorFrameAck ack
;
5861 host_impl_
->ReclaimResources(&ack
);
5862 host_impl_
->DidSwapBuffersComplete();
5863 EXPECT_EQ(swap_buffers_complete_
, 1);
5866 class CountingSoftwareDevice
: public SoftwareOutputDevice
{
5868 CountingSoftwareDevice() : frames_began_(0), frames_ended_(0) {}
5870 SkCanvas
* BeginPaint(const gfx::Rect
& damage_rect
) override
{
5872 return SoftwareOutputDevice::BeginPaint(damage_rect
);
5874 void EndPaint(SoftwareFrameData
* frame_data
) override
{
5876 SoftwareOutputDevice::EndPaint(frame_data
);
5879 int frames_began_
, frames_ended_
;
5882 TEST_F(LayerTreeHostImplTest
, ForcedDrawToSoftwareDeviceBasicRender
) {
5883 // No main thread evictions in resourceless software mode.
5884 set_reduce_memory_result(false);
5885 CountingSoftwareDevice
* software_device
= new CountingSoftwareDevice();
5886 EXPECT_TRUE(CreateHostImpl(
5888 FakeOutputSurface::CreateSoftware(make_scoped_ptr(software_device
))));
5889 host_impl_
->SetViewportSize(gfx::Size(50, 50));
5891 SetupScrollAndContentsLayers(gfx::Size(100, 100));
5893 const gfx::Transform external_transform
;
5894 const gfx::Rect external_viewport
;
5895 const gfx::Rect external_clip
;
5896 const bool resourceless_software_draw
= true;
5897 host_impl_
->SetExternalDrawConstraints(external_transform
,
5902 resourceless_software_draw
);
5904 EXPECT_EQ(0, software_device
->frames_began_
);
5905 EXPECT_EQ(0, software_device
->frames_ended_
);
5909 EXPECT_EQ(1, software_device
->frames_began_
);
5910 EXPECT_EQ(1, software_device
->frames_ended_
);
5912 // Call another API method that is likely to hit nullptr in this mode.
5913 scoped_refptr
<base::trace_event::TracedValue
> state
=
5914 make_scoped_refptr(new base::trace_event::TracedValue());
5915 host_impl_
->ActivationStateAsValueInto(state
.get());
5918 TEST_F(LayerTreeHostImplTest
,
5919 ForcedDrawToSoftwareDeviceSkipsUnsupportedLayers
) {
5920 set_reduce_memory_result(false);
5921 EXPECT_TRUE(CreateHostImpl(DefaultSettings(),
5922 FakeOutputSurface::CreateSoftware(
5923 make_scoped_ptr(new CountingSoftwareDevice
))));
5925 const gfx::Transform external_transform
;
5926 const gfx::Rect external_viewport
;
5927 const gfx::Rect external_clip
;
5928 const bool resourceless_software_draw
= true;
5929 host_impl_
->SetExternalDrawConstraints(external_transform
,
5934 resourceless_software_draw
);
5936 // SolidColorLayerImpl will be drawn.
5937 scoped_ptr
<SolidColorLayerImpl
> root_layer
=
5938 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
5940 // VideoLayerImpl will not be drawn.
5941 FakeVideoFrameProvider provider
;
5942 scoped_ptr
<VideoLayerImpl
> video_layer
= VideoLayerImpl::Create(
5943 host_impl_
->active_tree(), 2, &provider
, media::VIDEO_ROTATION_0
);
5944 video_layer
->SetBounds(gfx::Size(10, 10));
5945 video_layer
->SetContentBounds(gfx::Size(10, 10));
5946 video_layer
->SetDrawsContent(true);
5947 root_layer
->AddChild(video_layer
.Pass());
5948 SetupRootLayerImpl(root_layer
.Pass());
5950 LayerTreeHostImpl::FrameData frame
;
5951 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
5952 host_impl_
->DrawLayers(&frame
);
5953 host_impl_
->DidDrawAllLayers(frame
);
5955 EXPECT_EQ(1u, frame
.will_draw_layers
.size());
5956 EXPECT_EQ(host_impl_
->active_tree()->root_layer(), frame
.will_draw_layers
[0]);
5959 // Checks that we have a non-0 default allocation if we pass a context that
5960 // doesn't support memory management extensions.
5961 TEST_F(LayerTreeHostImplTest
, DefaultMemoryAllocation
) {
5962 LayerTreeSettings settings
;
5963 host_impl_
= LayerTreeHostImpl::Create(
5964 settings
, this, &proxy_
, &stats_instrumentation_
,
5965 shared_bitmap_manager_
.get(), gpu_memory_buffer_manager_
.get(),
5966 task_graph_runner_
.get(), 0);
5968 scoped_ptr
<OutputSurface
> output_surface(
5969 FakeOutputSurface::Create3d(TestWebGraphicsContext3D::Create()));
5970 host_impl_
->InitializeRenderer(output_surface
.Pass());
5971 EXPECT_LT(0ul, host_impl_
->memory_allocation_limit_bytes());
5974 TEST_F(LayerTreeHostImplTest
, MemoryPolicy
) {
5975 ManagedMemoryPolicy
policy1(
5976 456, gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
, 1000);
5977 int everything_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
5978 gpu::MemoryAllocation::CUTOFF_ALLOW_EVERYTHING
);
5979 int allow_nice_to_have_cutoff_value
=
5980 ManagedMemoryPolicy::PriorityCutoffToValue(
5981 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE
);
5982 int nothing_cutoff_value
= ManagedMemoryPolicy::PriorityCutoffToValue(
5983 gpu::MemoryAllocation::CUTOFF_ALLOW_NOTHING
);
5985 // GPU rasterization should be disabled by default on the tree(s)
5986 EXPECT_FALSE(host_impl_
->active_tree()->use_gpu_rasterization());
5987 EXPECT_TRUE(host_impl_
->pending_tree() == NULL
);
5989 host_impl_
->SetVisible(true);
5990 host_impl_
->SetMemoryPolicy(policy1
);
5991 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
5992 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
5994 host_impl_
->SetVisible(false);
5995 EXPECT_EQ(0u, current_limit_bytes_
);
5996 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
5998 host_impl_
->SetVisible(true);
5999 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
6000 EXPECT_EQ(everything_cutoff_value
, current_priority_cutoff_value_
);
6002 // Now enable GPU rasterization and test if we get nice to have cutoff,
6004 LayerTreeSettings settings
;
6005 settings
.gpu_rasterization_enabled
= true;
6006 CreateHostImpl(settings
, CreateOutputSurface());
6007 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6008 host_impl_
->SetHasGpuRasterizationTrigger(true);
6009 host_impl_
->SetVisible(true);
6010 host_impl_
->SetMemoryPolicy(policy1
);
6011 EXPECT_EQ(policy1
.bytes_limit_when_visible
, current_limit_bytes_
);
6012 EXPECT_EQ(allow_nice_to_have_cutoff_value
, current_priority_cutoff_value_
);
6014 host_impl_
->SetVisible(false);
6015 EXPECT_EQ(0u, current_limit_bytes_
);
6016 EXPECT_EQ(nothing_cutoff_value
, current_priority_cutoff_value_
);
6019 TEST_F(LayerTreeHostImplTest
, RequireHighResWhenVisible
) {
6020 ASSERT_TRUE(host_impl_
->active_tree());
6022 // RequiresHighResToDraw is set when new output surface is used.
6023 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6025 host_impl_
->ResetRequiresHighResToDraw();
6027 host_impl_
->SetVisible(false);
6028 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6029 host_impl_
->SetVisible(true);
6030 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6031 host_impl_
->SetVisible(false);
6032 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6034 host_impl_
->ResetRequiresHighResToDraw();
6036 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6037 host_impl_
->SetVisible(true);
6038 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6041 TEST_F(LayerTreeHostImplTest
, RequireHighResAfterGpuRasterizationToggles
) {
6042 ASSERT_TRUE(host_impl_
->active_tree());
6043 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
6045 // RequiresHighResToDraw is set when new output surface is used.
6046 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6048 host_impl_
->ResetRequiresHighResToDraw();
6050 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
6051 host_impl_
->SetHasGpuRasterizationTrigger(false);
6052 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6053 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6054 host_impl_
->SetHasGpuRasterizationTrigger(true);
6055 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6056 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6057 host_impl_
->SetHasGpuRasterizationTrigger(false);
6058 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6059 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6061 host_impl_
->ResetRequiresHighResToDraw();
6063 EXPECT_FALSE(host_impl_
->RequiresHighResToDraw());
6064 host_impl_
->SetHasGpuRasterizationTrigger(true);
6065 host_impl_
->UpdateTreeResourcesForGpuRasterizationIfNeeded();
6066 EXPECT_TRUE(host_impl_
->RequiresHighResToDraw());
6069 class LayerTreeHostImplTestPrepareTiles
: public LayerTreeHostImplTest
{
6071 void SetUp() override
{
6072 LayerTreeSettings settings
;
6073 settings
.impl_side_painting
= true;
6075 fake_host_impl_
= new FakeLayerTreeHostImpl(settings
, &proxy_
,
6076 shared_bitmap_manager_
.get(),
6077 task_graph_runner_
.get());
6078 host_impl_
.reset(fake_host_impl_
);
6079 host_impl_
->InitializeRenderer(CreateOutputSurface());
6080 host_impl_
->SetViewportSize(gfx::Size(10, 10));
6083 FakeLayerTreeHostImpl
* fake_host_impl_
;
6086 TEST_F(LayerTreeHostImplTestPrepareTiles
, PrepareTilesWhenInvisible
) {
6087 fake_host_impl_
->DidModifyTilePriorities();
6088 EXPECT_TRUE(fake_host_impl_
->prepare_tiles_needed());
6089 fake_host_impl_
->SetVisible(false);
6090 EXPECT_FALSE(fake_host_impl_
->prepare_tiles_needed());
6093 TEST_F(LayerTreeHostImplTest
, UIResourceManagement
) {
6094 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6095 TestWebGraphicsContext3D::Create();
6096 TestWebGraphicsContext3D
* context3d
= context
.get();
6097 scoped_ptr
<FakeOutputSurface
> output_surface
= FakeOutputSurface::Create3d();
6098 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
6100 EXPECT_EQ(0u, context3d
->NumTextures());
6102 UIResourceId ui_resource_id
= 1;
6103 bool is_opaque
= false;
6104 UIResourceBitmap
bitmap(gfx::Size(1, 1), is_opaque
);
6105 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6106 EXPECT_EQ(1u, context3d
->NumTextures());
6107 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6110 // Multiple requests with the same id is allowed. The previous texture is
6112 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6113 EXPECT_EQ(1u, context3d
->NumTextures());
6114 ResourceId id2
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6116 EXPECT_NE(id1
, id2
);
6118 // Deleting invalid UIResourceId is allowed and does not change state.
6119 host_impl_
->DeleteUIResource(-1);
6120 EXPECT_EQ(1u, context3d
->NumTextures());
6122 // Should return zero for invalid UIResourceId. Number of textures should
6124 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(-1));
6125 EXPECT_EQ(1u, context3d
->NumTextures());
6127 host_impl_
->DeleteUIResource(ui_resource_id
);
6128 EXPECT_EQ(0u, host_impl_
->ResourceIdForUIResource(ui_resource_id
));
6129 EXPECT_EQ(0u, context3d
->NumTextures());
6131 // Should not change state for multiple deletion on one UIResourceId
6132 host_impl_
->DeleteUIResource(ui_resource_id
);
6133 EXPECT_EQ(0u, context3d
->NumTextures());
6136 TEST_F(LayerTreeHostImplTest
, CreateETC1UIResource
) {
6137 scoped_ptr
<TestWebGraphicsContext3D
> context
=
6138 TestWebGraphicsContext3D::Create();
6139 TestWebGraphicsContext3D
* context3d
= context
.get();
6140 CreateHostImpl(DefaultSettings(), FakeOutputSurface::Create3d());
6142 EXPECT_EQ(0u, context3d
->NumTextures());
6144 gfx::Size
size(4, 4);
6145 // SkImageInfo has no support for ETC1. The |info| below contains the right
6146 // total pixel size for the bitmap but not the right height and width. The
6147 // correct width/height are passed directly to UIResourceBitmap.
6149 SkImageInfo::Make(4, 2, kAlpha_8_SkColorType
, kPremul_SkAlphaType
);
6150 skia::RefPtr
<SkPixelRef
> pixel_ref
=
6151 skia::AdoptRef(SkMallocPixelRef::NewAllocate(info
, 0, 0));
6152 pixel_ref
->setImmutable();
6153 UIResourceBitmap
bitmap(pixel_ref
, size
);
6154 UIResourceId ui_resource_id
= 1;
6155 host_impl_
->CreateUIResource(ui_resource_id
, bitmap
);
6156 EXPECT_EQ(1u, context3d
->NumTextures());
6157 ResourceId id1
= host_impl_
->ResourceIdForUIResource(ui_resource_id
);
6161 void ShutdownReleasesContext_Callback(scoped_ptr
<CopyOutputResult
> result
) {
6164 TEST_F(LayerTreeHostImplTest
, ShutdownReleasesContext
) {
6165 scoped_refptr
<TestContextProvider
> context_provider
=
6166 TestContextProvider::Create();
6168 CreateHostImpl(DefaultSettings(),
6169 FakeOutputSurface::Create3d(context_provider
));
6171 SetupRootLayerImpl(LayerImpl::Create(host_impl_
->active_tree(), 1));
6173 ScopedPtrVector
<CopyOutputRequest
> requests
;
6174 requests
.push_back(CopyOutputRequest::CreateRequest(
6175 base::Bind(&ShutdownReleasesContext_Callback
)));
6177 host_impl_
->active_tree()->root_layer()->PassCopyRequests(&requests
);
6179 LayerTreeHostImpl::FrameData frame
;
6180 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6181 host_impl_
->DrawLayers(&frame
);
6182 host_impl_
->DidDrawAllLayers(frame
);
6184 // The CopyOutputResult's callback has a ref on the ContextProvider and a
6185 // texture in a texture mailbox.
6186 EXPECT_FALSE(context_provider
->HasOneRef());
6187 EXPECT_EQ(1u, context_provider
->TestContext3d()->NumTextures());
6189 host_impl_
= nullptr;
6191 // The CopyOutputResult's callback was cancelled, the CopyOutputResult
6192 // released, and the texture deleted.
6193 EXPECT_TRUE(context_provider
->HasOneRef());
6194 EXPECT_EQ(0u, context_provider
->TestContext3d()->NumTextures());
6197 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldNotBubble
) {
6198 // When flinging via touch, only the child should scroll (we should not
6200 gfx::Size
surface_size(10, 10);
6201 gfx::Size
content_size(20, 20);
6202 scoped_ptr
<LayerImpl
> root_clip
=
6203 LayerImpl::Create(host_impl_
->active_tree(), 3);
6204 root_clip
->SetHasRenderSurface(true);
6206 scoped_ptr
<LayerImpl
> root
=
6207 CreateScrollableLayer(1, content_size
, root_clip
.get());
6208 root
->SetIsContainerForFixedPositionLayers(true);
6209 scoped_ptr
<LayerImpl
> child
=
6210 CreateScrollableLayer(2, content_size
, root_clip
.get());
6212 root
->AddChild(child
.Pass());
6213 int root_id
= root
->id();
6214 root_clip
->AddChild(root
.Pass());
6216 host_impl_
->SetViewportSize(surface_size
);
6217 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6218 host_impl_
->active_tree()->SetViewportLayersFromIds(Layer::INVALID_ID
, 3, 1,
6220 host_impl_
->active_tree()->DidBecomeActive();
6223 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6224 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6226 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6228 gfx::Vector2d
scroll_delta(0, 100);
6229 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6230 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6232 host_impl_
->ScrollEnd();
6234 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6235 host_impl_
->ProcessScrollDeltas();
6237 // Only the child should have scrolled.
6238 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6239 ExpectNone(*scroll_info
.get(), root_id
);
6243 TEST_F(LayerTreeHostImplTest
, TouchFlingShouldLockToFirstScrolledLayer
) {
6244 // Scroll a child layer beyond its maximum scroll range and make sure the
6245 // the scroll doesn't bubble up to the parent layer.
6246 gfx::Size
surface_size(10, 10);
6247 scoped_ptr
<LayerImpl
> root
= LayerImpl::Create(host_impl_
->active_tree(), 1);
6248 root
->SetHasRenderSurface(true);
6249 scoped_ptr
<LayerImpl
> root_scrolling
=
6250 CreateScrollableLayer(2, surface_size
, root
.get());
6252 scoped_ptr
<LayerImpl
> grand_child
=
6253 CreateScrollableLayer(4, surface_size
, root
.get());
6254 grand_child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 2));
6256 scoped_ptr
<LayerImpl
> child
=
6257 CreateScrollableLayer(3, surface_size
, root
.get());
6258 child
->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 4));
6259 child
->AddChild(grand_child
.Pass());
6261 root_scrolling
->AddChild(child
.Pass());
6262 root
->AddChild(root_scrolling
.Pass());
6263 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6264 host_impl_
->active_tree()->DidBecomeActive();
6265 host_impl_
->SetViewportSize(surface_size
);
6268 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
6270 host_impl_
->active_tree()->root_layer()->children()[0]->children()[0];
6271 LayerImpl
* grand_child
= child
->children()[0];
6273 gfx::Vector2d
scroll_delta(0, -2);
6274 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6275 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6276 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6278 // The grand child should have scrolled up to its limit.
6279 scroll_info
= host_impl_
->ProcessScrollDeltas();
6280 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
6281 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6282 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6284 // The child should have received the bubbled delta, but the locked
6285 // scrolling layer should remain set as the grand child.
6286 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6287 scroll_info
= host_impl_
->ProcessScrollDeltas();
6288 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6289 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6290 ExpectContains(*scroll_info
, child
->id(), scroll_delta
);
6291 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), grand_child
);
6293 // The first |ScrollBy| after the fling should re-lock the scrolling
6294 // layer to the first layer that scrolled, which is the child.
6295 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6296 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6297 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6299 // The child should have scrolled up to its limit.
6300 scroll_info
= host_impl_
->ProcessScrollDeltas();
6301 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6302 ExpectContains(*scroll_info
, grand_child
->id(), scroll_delta
);
6303 ExpectContains(*scroll_info
, child
->id(), scroll_delta
+ scroll_delta
);
6305 // As the locked layer is at it's limit, no further scrolling can occur.
6306 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
6307 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child
);
6308 host_impl_
->ScrollEnd();
6312 TEST_F(LayerTreeHostImplTest
, WheelFlingShouldBubble
) {
6313 // When flinging via wheel, the root should eventually scroll (we should
6315 gfx::Size
surface_size(10, 10);
6316 gfx::Size
content_size(20, 20);
6317 scoped_ptr
<LayerImpl
> root_clip
=
6318 LayerImpl::Create(host_impl_
->active_tree(), 3);
6319 root_clip
->SetHasRenderSurface(true);
6320 scoped_ptr
<LayerImpl
> root_scroll
=
6321 CreateScrollableLayer(1, content_size
, root_clip
.get());
6322 int root_scroll_id
= root_scroll
->id();
6323 scoped_ptr
<LayerImpl
> child
=
6324 CreateScrollableLayer(2, content_size
, root_clip
.get());
6326 root_scroll
->AddChild(child
.Pass());
6327 root_clip
->AddChild(root_scroll
.Pass());
6329 host_impl_
->SetViewportSize(surface_size
);
6330 host_impl_
->active_tree()->SetRootLayer(root_clip
.Pass());
6331 host_impl_
->active_tree()->DidBecomeActive();
6334 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6335 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6337 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
6339 gfx::Vector2d
scroll_delta(0, 100);
6340 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6341 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
6343 host_impl_
->ScrollEnd();
6345 scoped_ptr
<ScrollAndScaleSet
> scroll_info
=
6346 host_impl_
->ProcessScrollDeltas();
6348 // The root should have scrolled.
6349 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
6350 ExpectContains(*scroll_info
.get(), root_scroll_id
, gfx::Vector2d(0, 10));
6354 TEST_F(LayerTreeHostImplTest
, ScrollUnknownNotOnAncestorChain
) {
6355 // If we ray cast a scroller that is not on the first layer's ancestor chain,
6356 // we should return SCROLL_UNKNOWN.
6357 gfx::Size
content_size(100, 100);
6358 SetupScrollAndContentsLayers(content_size
);
6360 int scroll_layer_id
= 2;
6361 LayerImpl
* scroll_layer
=
6362 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6363 scroll_layer
->SetDrawsContent(true);
6365 int page_scale_layer_id
= 5;
6366 LayerImpl
* page_scale_layer
=
6367 host_impl_
->active_tree()->LayerById(page_scale_layer_id
);
6369 int occluder_layer_id
= 6;
6370 scoped_ptr
<LayerImpl
> occluder_layer
=
6371 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6372 occluder_layer
->SetDrawsContent(true);
6373 occluder_layer
->SetBounds(content_size
);
6374 occluder_layer
->SetContentBounds(content_size
);
6375 occluder_layer
->SetPosition(gfx::PointF());
6377 // The parent of the occluder is *above* the scroller.
6378 page_scale_layer
->AddChild(occluder_layer
.Pass());
6382 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6383 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6386 TEST_F(LayerTreeHostImplTest
, ScrollUnknownScrollAncestorMismatch
) {
6387 // If we ray cast a scroller this is on the first layer's ancestor chain, but
6388 // is not the first scroller we encounter when walking up from the layer, we
6389 // should also return SCROLL_UNKNOWN.
6390 gfx::Size
content_size(100, 100);
6391 SetupScrollAndContentsLayers(content_size
);
6393 int scroll_layer_id
= 2;
6394 LayerImpl
* scroll_layer
=
6395 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6396 scroll_layer
->SetDrawsContent(true);
6398 int occluder_layer_id
= 6;
6399 scoped_ptr
<LayerImpl
> occluder_layer
=
6400 LayerImpl::Create(host_impl_
->active_tree(), occluder_layer_id
);
6401 occluder_layer
->SetDrawsContent(true);
6402 occluder_layer
->SetBounds(content_size
);
6403 occluder_layer
->SetContentBounds(content_size
);
6404 occluder_layer
->SetPosition(gfx::PointF(-10.f
, -10.f
));
6406 int child_scroll_clip_layer_id
= 7;
6407 scoped_ptr
<LayerImpl
> child_scroll_clip
=
6408 LayerImpl::Create(host_impl_
->active_tree(), child_scroll_clip_layer_id
);
6410 int child_scroll_layer_id
= 8;
6411 scoped_ptr
<LayerImpl
> child_scroll
= CreateScrollableLayer(
6412 child_scroll_layer_id
, content_size
, child_scroll_clip
.get());
6414 child_scroll
->SetPosition(gfx::PointF(10.f
, 10.f
));
6416 child_scroll
->AddChild(occluder_layer
.Pass());
6417 scroll_layer
->AddChild(child_scroll
.Pass());
6421 EXPECT_EQ(InputHandler::SCROLL_UNKNOWN
,
6422 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6425 TEST_F(LayerTreeHostImplTest
, NotScrollInvisibleScroller
) {
6426 gfx::Size
content_size(100, 100);
6427 SetupScrollAndContentsLayers(content_size
);
6429 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6431 int scroll_layer_id
= 2;
6432 LayerImpl
* scroll_layer
=
6433 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6435 int child_scroll_layer_id
= 7;
6436 scoped_ptr
<LayerImpl
> child_scroll
=
6437 CreateScrollableLayer(child_scroll_layer_id
, content_size
, root
);
6438 child_scroll
->SetDrawsContent(false);
6440 scroll_layer
->AddChild(child_scroll
.Pass());
6444 // We should not have scrolled |child_scroll| even though we technically "hit"
6445 // it. The reason for this is that if the scrolling the scroll would not move
6446 // any layer that is a drawn RSLL member, then we can ignore the hit.
6448 // Why SCROLL_STARTED? In this case, it's because we've bubbled out and
6449 // started scrolling the inner viewport.
6450 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6451 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6453 EXPECT_EQ(2, host_impl_
->CurrentlyScrollingLayer()->id());
6456 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleDescendent
) {
6457 gfx::Size
content_size(100, 100);
6458 SetupScrollAndContentsLayers(content_size
);
6460 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6461 LayerImpl
* root_scroll_layer
= host_impl_
->active_tree()->LayerById(2);
6463 scoped_ptr
<LayerImpl
> invisible_scroll_layer
=
6464 CreateScrollableLayer(7, content_size
, root
);
6465 invisible_scroll_layer
->SetDrawsContent(false);
6467 scoped_ptr
<LayerImpl
> child_layer
=
6468 LayerImpl::Create(host_impl_
->active_tree(), 8);
6469 child_layer
->SetDrawsContent(false);
6471 scoped_ptr
<LayerImpl
> grand_child_layer
=
6472 LayerImpl::Create(host_impl_
->active_tree(), 9);
6473 grand_child_layer
->SetDrawsContent(true);
6474 grand_child_layer
->SetBounds(content_size
);
6475 grand_child_layer
->SetContentBounds(content_size
);
6476 // Move the grand child so it's not hit by our test point.
6477 grand_child_layer
->SetPosition(gfx::PointF(10.f
, 10.f
));
6479 child_layer
->AddChild(grand_child_layer
.Pass());
6480 invisible_scroll_layer
->AddChild(child_layer
.Pass());
6481 root_scroll_layer
->AddChild(invisible_scroll_layer
.Pass());
6485 // We should have scrolled |invisible_scroll_layer| as it was hit and it has
6486 // a descendant which is a drawn RSLL member.
6487 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6488 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6490 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6493 TEST_F(LayerTreeHostImplTest
, ScrollInvisibleScrollerWithVisibleScrollChild
) {
6494 // This test case is very similar to the one above with one key difference:
6495 // the invisible scroller has a scroll child that is indeed draw contents.
6496 // If we attempt to initiate a gesture scroll off of the visible scroll child
6497 // we should still start the scroll child.
6498 gfx::Size
content_size(100, 100);
6499 SetupScrollAndContentsLayers(content_size
);
6501 LayerImpl
* root
= host_impl_
->active_tree()->LayerById(1);
6503 int scroll_layer_id
= 2;
6504 LayerImpl
* scroll_layer
=
6505 host_impl_
->active_tree()->LayerById(scroll_layer_id
);
6507 int scroll_child_id
= 6;
6508 scoped_ptr
<LayerImpl
> scroll_child
=
6509 LayerImpl::Create(host_impl_
->active_tree(), scroll_child_id
);
6510 scroll_child
->SetDrawsContent(true);
6511 scroll_child
->SetBounds(content_size
);
6512 scroll_child
->SetContentBounds(content_size
);
6513 // Move the scroll child so it's not hit by our test point.
6514 scroll_child
->SetPosition(gfx::PointF(10.f
, 10.f
));
6516 int invisible_scroll_layer_id
= 7;
6517 scoped_ptr
<LayerImpl
> invisible_scroll
=
6518 CreateScrollableLayer(invisible_scroll_layer_id
, content_size
, root
);
6519 invisible_scroll
->SetDrawsContent(false);
6521 int container_id
= 8;
6522 scoped_ptr
<LayerImpl
> container
=
6523 LayerImpl::Create(host_impl_
->active_tree(), container_id
);
6525 scoped_ptr
<std::set
<LayerImpl
*>> scroll_children(new std::set
<LayerImpl
*>);
6526 scroll_children
->insert(scroll_child
.get());
6527 invisible_scroll
->SetScrollChildren(scroll_children
.release());
6529 scroll_child
->SetScrollParent(invisible_scroll
.get());
6531 container
->AddChild(invisible_scroll
.Pass());
6532 container
->AddChild(scroll_child
.Pass());
6534 scroll_layer
->AddChild(container
.Pass());
6538 // We should have scrolled |child_scroll| even though it is invisible.
6539 // The reason for this is that if the scrolling the scroll would move a layer
6540 // that is a drawn RSLL member, then we should accept this hit.
6541 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6542 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
6544 EXPECT_EQ(7, host_impl_
->CurrentlyScrollingLayer()->id());
6547 // Make sure LatencyInfo carried by LatencyInfoSwapPromise are passed
6548 // to CompositorFrameMetadata after SwapBuffers();
6549 TEST_F(LayerTreeHostImplTest
, LatencyInfoPassedToCompositorFrameMetadata
) {
6550 scoped_ptr
<SolidColorLayerImpl
> root
=
6551 SolidColorLayerImpl::Create(host_impl_
->active_tree(), 1);
6552 root
->SetPosition(gfx::PointF());
6553 root
->SetBounds(gfx::Size(10, 10));
6554 root
->SetContentBounds(gfx::Size(10, 10));
6555 root
->SetDrawsContent(true);
6556 root
->SetHasRenderSurface(true);
6558 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6560 FakeOutputSurface
* fake_output_surface
=
6561 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6563 const std::vector
<ui::LatencyInfo
>& metadata_latency_before
=
6564 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6565 EXPECT_TRUE(metadata_latency_before
.empty());
6567 ui::LatencyInfo latency_info
;
6568 latency_info
.AddLatencyNumber(
6569 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, 0);
6570 scoped_ptr
<SwapPromise
> swap_promise(
6571 new LatencyInfoSwapPromise(latency_info
));
6572 host_impl_
->active_tree()->QueueSwapPromise(swap_promise
.Pass());
6573 host_impl_
->SetNeedsRedraw();
6575 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6576 LayerTreeHostImpl::FrameData frame
;
6577 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6578 host_impl_
->DrawLayers(&frame
);
6579 host_impl_
->DidDrawAllLayers(frame
);
6580 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6582 const std::vector
<ui::LatencyInfo
>& metadata_latency_after
=
6583 fake_output_surface
->last_sent_frame().metadata
.latency_info
;
6584 EXPECT_EQ(1u, metadata_latency_after
.size());
6585 EXPECT_TRUE(metadata_latency_after
[0].FindLatency(
6586 ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT
, 0, NULL
));
6589 TEST_F(LayerTreeHostImplTest
, SelectionBoundsPassedToCompositorFrameMetadata
) {
6590 int root_layer_id
= 1;
6591 scoped_ptr
<SolidColorLayerImpl
> root
=
6592 SolidColorLayerImpl::Create(host_impl_
->active_tree(), root_layer_id
);
6593 root
->SetPosition(gfx::PointF());
6594 root
->SetBounds(gfx::Size(10, 10));
6595 root
->SetContentBounds(gfx::Size(10, 10));
6596 root
->SetDrawsContent(true);
6597 root
->SetHasRenderSurface(true);
6599 host_impl_
->active_tree()->SetRootLayer(root
.Pass());
6601 // Ensure the default frame selection bounds are empty.
6602 FakeOutputSurface
* fake_output_surface
=
6603 static_cast<FakeOutputSurface
*>(host_impl_
->output_surface());
6604 const ViewportSelection
& selection_before
=
6605 fake_output_surface
->last_sent_frame().metadata
.selection
;
6606 EXPECT_EQ(ViewportSelectionBound(), selection_before
.start
);
6607 EXPECT_EQ(ViewportSelectionBound(), selection_before
.end
);
6609 // Plumb the layer-local selection bounds.
6610 gfx::PointF
selection_top(5, 0);
6611 gfx::PointF
selection_bottom(5, 5);
6612 LayerSelection selection
;
6613 selection
.start
.type
= SELECTION_BOUND_CENTER
;
6614 selection
.start
.layer_id
= root_layer_id
;
6615 selection
.start
.edge_bottom
= selection_bottom
;
6616 selection
.start
.edge_top
= selection_top
;
6617 selection
.end
= selection
.start
;
6618 host_impl_
->active_tree()->RegisterSelection(selection
);
6620 // Trigger a draw-swap sequence.
6621 host_impl_
->SetNeedsRedraw();
6623 gfx::Rect
full_frame_damage(host_impl_
->DrawViewportSize());
6624 LayerTreeHostImpl::FrameData frame
;
6625 EXPECT_EQ(DRAW_SUCCESS
, host_impl_
->PrepareToDraw(&frame
));
6626 host_impl_
->DrawLayers(&frame
);
6627 host_impl_
->DidDrawAllLayers(frame
);
6628 EXPECT_TRUE(host_impl_
->SwapBuffers(frame
));
6630 // Ensure the selection bounds have propagated to the frame metadata.
6631 const ViewportSelection
& selection_after
=
6632 fake_output_surface
->last_sent_frame().metadata
.selection
;
6633 EXPECT_EQ(selection
.start
.type
, selection_after
.start
.type
);
6634 EXPECT_EQ(selection
.end
.type
, selection_after
.end
.type
);
6635 EXPECT_EQ(selection_bottom
, selection_after
.start
.edge_bottom
);
6636 EXPECT_EQ(selection_top
, selection_after
.start
.edge_top
);
6637 EXPECT_TRUE(selection_after
.start
.visible
);
6638 EXPECT_TRUE(selection_after
.start
.visible
);
6641 class SimpleSwapPromiseMonitor
: public SwapPromiseMonitor
{
6643 SimpleSwapPromiseMonitor(LayerTreeHost
* layer_tree_host
,
6644 LayerTreeHostImpl
* layer_tree_host_impl
,
6645 int* set_needs_commit_count
,
6646 int* set_needs_redraw_count
,
6647 int* forward_to_main_count
)
6648 : SwapPromiseMonitor(layer_tree_host
, layer_tree_host_impl
),
6649 set_needs_commit_count_(set_needs_commit_count
),
6650 set_needs_redraw_count_(set_needs_redraw_count
),
6651 forward_to_main_count_(forward_to_main_count
) {}
6653 ~SimpleSwapPromiseMonitor() override
{}
6655 void OnSetNeedsCommitOnMain() override
{ (*set_needs_commit_count_
)++; }
6657 void OnSetNeedsRedrawOnImpl() override
{ (*set_needs_redraw_count_
)++; }
6659 void OnForwardScrollUpdateToMainThreadOnImpl() override
{
6660 (*forward_to_main_count_
)++;
6664 int* set_needs_commit_count_
;
6665 int* set_needs_redraw_count_
;
6666 int* forward_to_main_count_
;
6669 TEST_F(LayerTreeHostImplTest
, SimpleSwapPromiseMonitor
) {
6670 int set_needs_commit_count
= 0;
6671 int set_needs_redraw_count
= 0;
6672 int forward_to_main_count
= 0;
6675 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6676 new SimpleSwapPromiseMonitor(NULL
,
6678 &set_needs_commit_count
,
6679 &set_needs_redraw_count
,
6680 &forward_to_main_count
));
6681 host_impl_
->SetNeedsRedraw();
6682 EXPECT_EQ(0, set_needs_commit_count
);
6683 EXPECT_EQ(1, set_needs_redraw_count
);
6684 EXPECT_EQ(0, forward_to_main_count
);
6687 // Now the monitor is destroyed, SetNeedsRedraw() is no longer being
6689 host_impl_
->SetNeedsRedraw();
6690 EXPECT_EQ(0, set_needs_commit_count
);
6691 EXPECT_EQ(1, set_needs_redraw_count
);
6692 EXPECT_EQ(0, forward_to_main_count
);
6695 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6696 new SimpleSwapPromiseMonitor(NULL
,
6698 &set_needs_commit_count
,
6699 &set_needs_redraw_count
,
6700 &forward_to_main_count
));
6701 host_impl_
->SetNeedsRedrawRect(gfx::Rect(10, 10));
6702 EXPECT_EQ(0, set_needs_commit_count
);
6703 EXPECT_EQ(2, set_needs_redraw_count
);
6704 EXPECT_EQ(0, forward_to_main_count
);
6708 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6709 new SimpleSwapPromiseMonitor(NULL
,
6711 &set_needs_commit_count
,
6712 &set_needs_redraw_count
,
6713 &forward_to_main_count
));
6714 // Empty damage rect won't signal the monitor.
6715 host_impl_
->SetNeedsRedrawRect(gfx::Rect());
6716 EXPECT_EQ(0, set_needs_commit_count
);
6717 EXPECT_EQ(2, set_needs_redraw_count
);
6718 EXPECT_EQ(0, forward_to_main_count
);
6722 set_needs_commit_count
= 0;
6723 set_needs_redraw_count
= 0;
6724 forward_to_main_count
= 0;
6725 scoped_ptr
<SimpleSwapPromiseMonitor
> swap_promise_monitor(
6726 new SimpleSwapPromiseMonitor(NULL
,
6728 &set_needs_commit_count
,
6729 &set_needs_redraw_count
,
6730 &forward_to_main_count
));
6731 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
6733 // Scrolling normally should not trigger any forwarding.
6734 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6735 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6737 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6738 host_impl_
->ScrollEnd();
6740 EXPECT_EQ(0, set_needs_commit_count
);
6741 EXPECT_EQ(1, set_needs_redraw_count
);
6742 EXPECT_EQ(0, forward_to_main_count
);
6744 // Scrolling with a scroll handler should defer the swap to the main
6746 scroll_layer
->SetHaveScrollEventHandlers(true);
6747 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6748 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6750 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll
);
6751 host_impl_
->ScrollEnd();
6753 EXPECT_EQ(0, set_needs_commit_count
);
6754 EXPECT_EQ(2, set_needs_redraw_count
);
6755 EXPECT_EQ(1, forward_to_main_count
);
6759 class LayerTreeHostImplWithTopControlsTest
: public LayerTreeHostImplTest
{
6761 void SetUp() override
{
6762 LayerTreeSettings settings
= DefaultSettings();
6763 CreateHostImpl(settings
, CreateOutputSurface());
6764 host_impl_
->active_tree()->set_top_controls_height(top_controls_height_
);
6765 host_impl_
->sync_tree()->set_top_controls_height(top_controls_height_
);
6766 host_impl_
->active_tree()->SetCurrentTopControlsShownRatio(1.f
);
6770 static const int top_controls_height_
;
6773 const int LayerTreeHostImplWithTopControlsTest::top_controls_height_
= 50;
6775 TEST_F(LayerTreeHostImplWithTopControlsTest
, NoIdleAnimations
) {
6776 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6777 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6778 host_impl_
->Animate(base::TimeTicks());
6779 EXPECT_FALSE(did_request_redraw_
);
6782 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsHeightIsCommitted
) {
6783 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6784 EXPECT_FALSE(did_request_redraw_
);
6785 host_impl_
->CreatePendingTree();
6786 host_impl_
->sync_tree()->set_top_controls_height(100);
6787 host_impl_
->ActivateSyncTree();
6788 EXPECT_EQ(100, host_impl_
->top_controls_manager()->TopControlsHeight());
6791 TEST_F(LayerTreeHostImplWithTopControlsTest
,
6792 TopControlsStayFullyVisibleOnHeightChange
) {
6793 SetupScrollAndContentsLayers(gfx::Size(100, 100));
6794 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6796 host_impl_
->CreatePendingTree();
6797 host_impl_
->sync_tree()->set_top_controls_height(0);
6798 host_impl_
->ActivateSyncTree();
6799 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6801 host_impl_
->CreatePendingTree();
6802 host_impl_
->sync_tree()->set_top_controls_height(50);
6803 host_impl_
->ActivateSyncTree();
6804 EXPECT_EQ(0.f
, host_impl_
->top_controls_manager()->ControlsTopOffset());
6807 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationScheduling
) {
6808 SetupScrollAndContentsLayers(gfx::Size(100, 100))
6809 ->PushScrollOffsetFromMainThread(gfx::ScrollOffset(0, 10));
6810 host_impl_
->DidChangeTopControlsPosition();
6811 EXPECT_TRUE(did_request_animate_
);
6812 EXPECT_TRUE(did_request_redraw_
);
6815 TEST_F(LayerTreeHostImplWithTopControlsTest
, ScrollHandledByTopControls
) {
6816 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6817 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6818 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6819 BOTH
, SHOWN
, false);
6822 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6823 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6824 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6825 EXPECT_EQ(gfx::Vector2dF().ToString(),
6826 scroll_layer
->CurrentScrollOffset().ToString());
6828 // Scroll just the top controls and verify that the scroll succeeds.
6829 const float residue
= 10;
6830 float offset
= top_controls_height_
- residue
;
6832 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6833 EXPECT_FLOAT_EQ(-offset
,
6834 host_impl_
->top_controls_manager()->ControlsTopOffset());
6835 EXPECT_EQ(gfx::Vector2dF().ToString(),
6836 scroll_layer
->CurrentScrollOffset().ToString());
6838 // Scroll across the boundary
6839 const float content_scroll
= 20;
6840 offset
= residue
+ content_scroll
;
6842 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6843 EXPECT_EQ(-top_controls_height_
,
6844 host_impl_
->top_controls_manager()->ControlsTopOffset());
6845 EXPECT_EQ(gfx::Vector2dF(0, content_scroll
).ToString(),
6846 scroll_layer
->CurrentScrollOffset().ToString());
6848 // Now scroll back to the top of the content
6849 offset
= -content_scroll
;
6851 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6852 EXPECT_EQ(-top_controls_height_
,
6853 host_impl_
->top_controls_manager()->ControlsTopOffset());
6854 EXPECT_EQ(gfx::Vector2dF().ToString(),
6855 scroll_layer
->CurrentScrollOffset().ToString());
6857 // And scroll the top controls completely into view
6858 offset
= -top_controls_height_
;
6860 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6861 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6862 EXPECT_EQ(gfx::Vector2dF().ToString(),
6863 scroll_layer
->CurrentScrollOffset().ToString());
6865 // And attempt to scroll past the end
6867 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6868 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6869 EXPECT_EQ(gfx::Vector2dF().ToString(),
6870 scroll_layer
->CurrentScrollOffset().ToString());
6872 host_impl_
->ScrollEnd();
6875 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAtOrigin
) {
6876 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6877 host_impl_
->SetViewportSize(gfx::Size(100, 200));
6878 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6879 BOTH
, SHOWN
, false);
6882 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6883 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6884 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6885 EXPECT_EQ(gfx::Vector2dF().ToString(),
6886 scroll_layer
->CurrentScrollOffset().ToString());
6888 // Scroll the top controls partially.
6889 const float residue
= 35;
6890 float offset
= top_controls_height_
- residue
;
6892 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6893 EXPECT_FLOAT_EQ(-offset
,
6894 host_impl_
->top_controls_manager()->ControlsTopOffset());
6895 EXPECT_EQ(gfx::Vector2dF().ToString(),
6896 scroll_layer
->CurrentScrollOffset().ToString());
6898 did_request_redraw_
= false;
6899 did_request_animate_
= false;
6900 did_request_commit_
= false;
6902 // End the scroll while the controls are still offset from their limit.
6903 host_impl_
->ScrollEnd();
6904 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6905 EXPECT_TRUE(did_request_animate_
);
6906 EXPECT_TRUE(did_request_redraw_
);
6907 EXPECT_FALSE(did_request_commit_
);
6909 // The top controls should properly animate until finished, despite the scroll
6910 // offset being at the origin.
6911 base::TimeTicks animation_time
= base::TimeTicks::Now();
6912 while (did_request_animate_
) {
6913 did_request_redraw_
= false;
6914 did_request_animate_
= false;
6915 did_request_commit_
= false;
6918 host_impl_
->top_controls_manager()->ControlsTopOffset();
6920 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6921 host_impl_
->Animate(animation_time
);
6922 EXPECT_EQ(gfx::Vector2dF().ToString(),
6923 scroll_layer
->CurrentScrollOffset().ToString());
6926 host_impl_
->top_controls_manager()->ControlsTopOffset();
6928 // No commit is needed as the controls are animating the content offset,
6929 // not the scroll offset.
6930 EXPECT_FALSE(did_request_commit_
);
6932 if (new_offset
!= old_offset
)
6933 EXPECT_TRUE(did_request_redraw_
);
6935 if (new_offset
!= 0) {
6936 EXPECT_TRUE(host_impl_
->top_controls_manager()->animation());
6937 EXPECT_TRUE(did_request_animate_
);
6940 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
6943 TEST_F(LayerTreeHostImplWithTopControlsTest
, TopControlsAnimationAfterScroll
) {
6944 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
6945 host_impl_
->SetViewportSize(gfx::Size(100, 100));
6946 host_impl_
->top_controls_manager()->UpdateTopControlsState(
6947 BOTH
, SHOWN
, false);
6948 float initial_scroll_offset
= 50;
6949 scroll_layer
->PushScrollOffsetFromMainThread(
6950 gfx::ScrollOffset(0, initial_scroll_offset
));
6953 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
6954 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
6955 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
6956 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6957 scroll_layer
->CurrentScrollOffset().ToString());
6959 // Scroll the top controls partially.
6960 const float residue
= 15;
6961 float offset
= top_controls_height_
- residue
;
6963 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
6964 EXPECT_FLOAT_EQ(-offset
,
6965 host_impl_
->top_controls_manager()->ControlsTopOffset());
6966 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
6967 scroll_layer
->CurrentScrollOffset().ToString());
6969 did_request_redraw_
= false;
6970 did_request_animate_
= false;
6971 did_request_commit_
= false;
6973 // End the scroll while the controls are still offset from the limit.
6974 host_impl_
->ScrollEnd();
6975 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
6976 EXPECT_TRUE(did_request_animate_
);
6977 EXPECT_TRUE(did_request_redraw_
);
6978 EXPECT_FALSE(did_request_commit_
);
6980 // Animate the top controls to the limit.
6981 base::TimeTicks animation_time
= base::TimeTicks::Now();
6982 while (did_request_animate_
) {
6983 did_request_redraw_
= false;
6984 did_request_animate_
= false;
6985 did_request_commit_
= false;
6988 host_impl_
->top_controls_manager()->ControlsTopOffset();
6990 animation_time
+= base::TimeDelta::FromMilliseconds(5);
6991 host_impl_
->Animate(animation_time
);
6994 host_impl_
->top_controls_manager()->ControlsTopOffset();
6996 if (new_offset
!= old_offset
) {
6997 EXPECT_TRUE(did_request_redraw_
);
6998 EXPECT_TRUE(did_request_commit_
);
7001 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7002 EXPECT_EQ(-top_controls_height_
,
7003 host_impl_
->top_controls_manager()->ControlsTopOffset());
7006 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7007 TopControlsAnimationAfterMainThreadFlingStopped
) {
7008 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7009 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7010 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7012 float initial_scroll_offset
= 50;
7013 scroll_layer
->PushScrollOffsetFromMainThread(
7014 gfx::ScrollOffset(0, initial_scroll_offset
));
7017 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7018 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7019 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7020 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7021 scroll_layer
->CurrentScrollOffset().ToString());
7023 // Scroll the top controls partially.
7024 const float residue
= 15;
7025 float offset
= top_controls_height_
- residue
;
7027 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7028 EXPECT_FLOAT_EQ(-offset
,
7029 host_impl_
->top_controls_manager()->ControlsTopOffset());
7030 EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset
).ToString(),
7031 scroll_layer
->CurrentScrollOffset().ToString());
7033 did_request_redraw_
= false;
7034 did_request_animate_
= false;
7035 did_request_commit_
= false;
7037 // End the fling while the controls are still offset from the limit.
7038 host_impl_
->MainThreadHasStoppedFlinging();
7039 ASSERT_TRUE(host_impl_
->top_controls_manager()->animation());
7040 EXPECT_TRUE(did_request_animate_
);
7041 EXPECT_TRUE(did_request_redraw_
);
7042 EXPECT_FALSE(did_request_commit_
);
7044 // Animate the top controls to the limit.
7045 base::TimeTicks animation_time
= base::TimeTicks::Now();
7046 while (did_request_animate_
) {
7047 did_request_redraw_
= false;
7048 did_request_animate_
= false;
7049 did_request_commit_
= false;
7051 float old_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7053 animation_time
+= base::TimeDelta::FromMilliseconds(5);
7054 host_impl_
->Animate(animation_time
);
7056 float new_offset
= host_impl_
->top_controls_manager()->ControlsTopOffset();
7058 if (new_offset
!= old_offset
) {
7059 EXPECT_TRUE(did_request_redraw_
);
7060 EXPECT_TRUE(did_request_commit_
);
7063 EXPECT_FALSE(host_impl_
->top_controls_manager()->animation());
7064 EXPECT_EQ(-top_controls_height_
,
7065 host_impl_
->top_controls_manager()->ControlsTopOffset());
7068 TEST_F(LayerTreeHostImplWithTopControlsTest
,
7069 TopControlsScrollDeltaInOverScroll
) {
7070 // test varifies that the overscroll delta should not have accumulated in
7071 // the top controls if we do a hide and show without releasing finger.
7073 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 200));
7074 host_impl_
->SetViewportSize(gfx::Size(100, 100));
7075 host_impl_
->top_controls_manager()->UpdateTopControlsState(BOTH
, SHOWN
,
7079 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7080 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7081 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7085 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7086 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7087 EXPECT_EQ(gfx::Vector2dF().ToString(),
7088 scroll_layer
->CurrentScrollOffset().ToString());
7091 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7092 EXPECT_EQ(gfx::Vector2dF(0, offset
).ToString(),
7093 scroll_layer
->CurrentScrollOffset().ToString());
7096 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset
)).did_scroll
);
7098 // Should have fully scrolled
7099 EXPECT_EQ(gfx::Vector2dF(0, scroll_layer
->MaxScrollOffset().y()).ToString(),
7100 scroll_layer
->CurrentScrollOffset().ToString());
7102 float overscrollamount
= 10;
7104 // Overscroll the content
7106 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, overscrollamount
))
7108 EXPECT_EQ(gfx::Vector2dF(0, 2 * offset
).ToString(),
7109 scroll_layer
->CurrentScrollOffset().ToString());
7110 EXPECT_EQ(gfx::Vector2dF(0, overscrollamount
).ToString(),
7111 host_impl_
->accumulated_root_overscroll().ToString());
7113 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -2 * offset
))
7115 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7116 scroll_layer
->CurrentScrollOffset().ToString());
7117 EXPECT_EQ(-offset
, host_impl_
->top_controls_manager()->ControlsTopOffset());
7120 host_impl_
->ScrollBy(gfx::Point(), gfx::Vector2d(0, -offset
)).did_scroll
);
7121 EXPECT_EQ(gfx::Vector2dF(0, 0).ToString(),
7122 scroll_layer
->CurrentScrollOffset().ToString());
7124 // Top controls should be fully visible
7125 EXPECT_EQ(0, host_impl_
->top_controls_manager()->ControlsTopOffset());
7127 host_impl_
->ScrollEnd();
7130 class LayerTreeHostImplVirtualViewportTest
: public LayerTreeHostImplTest
{
7132 void SetupVirtualViewportLayers(const gfx::Size
& content_size
,
7133 const gfx::Size
& outer_viewport
,
7134 const gfx::Size
& inner_viewport
) {
7135 LayerTreeImpl
* layer_tree_impl
= host_impl_
->active_tree();
7136 const int kOuterViewportClipLayerId
= 6;
7137 const int kOuterViewportScrollLayerId
= 7;
7138 const int kInnerViewportScrollLayerId
= 2;
7139 const int kInnerViewportClipLayerId
= 4;
7140 const int kPageScaleLayerId
= 5;
7142 scoped_ptr
<LayerImpl
> inner_scroll
=
7143 LayerImpl::Create(layer_tree_impl
, kInnerViewportScrollLayerId
);
7144 inner_scroll
->SetIsContainerForFixedPositionLayers(true);
7145 inner_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7147 scoped_ptr
<LayerImpl
> inner_clip
=
7148 LayerImpl::Create(layer_tree_impl
, kInnerViewportClipLayerId
);
7149 inner_clip
->SetBounds(inner_viewport
);
7151 scoped_ptr
<LayerImpl
> page_scale
=
7152 LayerImpl::Create(layer_tree_impl
, kPageScaleLayerId
);
7154 inner_scroll
->SetScrollClipLayer(inner_clip
->id());
7155 inner_scroll
->SetBounds(outer_viewport
);
7156 inner_scroll
->SetContentBounds(outer_viewport
);
7157 inner_scroll
->SetPosition(gfx::PointF());
7159 scoped_ptr
<LayerImpl
> outer_clip
=
7160 LayerImpl::Create(layer_tree_impl
, kOuterViewportClipLayerId
);
7161 outer_clip
->SetBounds(outer_viewport
);
7162 outer_clip
->SetIsContainerForFixedPositionLayers(true);
7164 scoped_ptr
<LayerImpl
> outer_scroll
=
7165 LayerImpl::Create(layer_tree_impl
, kOuterViewportScrollLayerId
);
7166 outer_scroll
->SetScrollClipLayer(outer_clip
->id());
7167 outer_scroll
->PushScrollOffsetFromMainThread(gfx::ScrollOffset());
7168 outer_scroll
->SetBounds(content_size
);
7169 outer_scroll
->SetContentBounds(content_size
);
7170 outer_scroll
->SetPosition(gfx::PointF());
7172 scoped_ptr
<LayerImpl
> contents
=
7173 LayerImpl::Create(layer_tree_impl
, 8);
7174 contents
->SetDrawsContent(true);
7175 contents
->SetBounds(content_size
);
7176 contents
->SetContentBounds(content_size
);
7177 contents
->SetPosition(gfx::PointF());
7179 outer_scroll
->AddChild(contents
.Pass());
7180 outer_clip
->AddChild(outer_scroll
.Pass());
7181 inner_scroll
->AddChild(outer_clip
.Pass());
7182 page_scale
->AddChild(inner_scroll
.Pass());
7183 inner_clip
->AddChild(page_scale
.Pass());
7185 inner_clip
->SetHasRenderSurface(true);
7186 layer_tree_impl
->SetRootLayer(inner_clip
.Pass());
7187 layer_tree_impl
->SetViewportLayersFromIds(
7188 Layer::INVALID_ID
, kPageScaleLayerId
, kInnerViewportScrollLayerId
,
7189 kOuterViewportScrollLayerId
);
7191 host_impl_
->active_tree()->DidBecomeActive();
7195 TEST_F(LayerTreeHostImplVirtualViewportTest
, ScrollBothInnerAndOuterLayer
) {
7196 gfx::Size content_size
= gfx::Size(100, 160);
7197 gfx::Size outer_viewport
= gfx::Size(50, 80);
7198 gfx::Size inner_viewport
= gfx::Size(25, 40);
7200 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7202 TestScrollOffsetDelegate scroll_delegate
;
7203 host_impl_
->SetRootLayerScrollOffsetDelegate(&scroll_delegate
);
7205 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7206 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7209 gfx::ScrollOffset inner_expected
;
7210 gfx::ScrollOffset outer_expected
;
7211 EXPECT_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7212 EXPECT_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7214 gfx::ScrollOffset
current_offset(70.f
, 100.f
);
7216 scroll_delegate
.set_getter_return_value(current_offset
);
7217 host_impl_
->OnRootLayerDelegatedScrollOffsetChanged();
7218 EXPECT_EQ(gfx::ScrollOffset(25.f
, 40.f
), inner_scroll
->MaxScrollOffset());
7219 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
), outer_scroll
->MaxScrollOffset());
7221 // Outer viewport scrolls first. Then the rest is applied to the inner
7223 EXPECT_EQ(gfx::ScrollOffset(20.f
, 20.f
),
7224 inner_scroll
->CurrentScrollOffset());
7225 EXPECT_EQ(gfx::ScrollOffset(50.f
, 80.f
),
7226 outer_scroll
->CurrentScrollOffset());
7230 TEST_F(LayerTreeHostImplVirtualViewportTest
, FlingScrollBubblesToInner
) {
7231 gfx::Size content_size
= gfx::Size(100, 160);
7232 gfx::Size outer_viewport
= gfx::Size(50, 80);
7233 gfx::Size inner_viewport
= gfx::Size(25, 40);
7235 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7237 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7238 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7241 gfx::Vector2dF inner_expected
;
7242 gfx::Vector2dF outer_expected
;
7243 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7244 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7246 // Make sure the fling goes to the outer viewport first
7247 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7248 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7249 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7251 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7252 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7253 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7255 host_impl_
->ScrollEnd();
7257 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7258 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7260 // Fling past the outer viewport boundry, make sure inner viewport scrolls.
7261 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7262 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7263 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7265 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7266 outer_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7268 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7269 inner_expected
+= gfx::Vector2dF(scroll_delta
.x(), scroll_delta
.y());
7271 host_impl_
->ScrollEnd();
7273 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7274 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7278 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7279 DiagonalScrollBubblesPerfectlyToInner
) {
7280 gfx::Size content_size
= gfx::Size(100, 160);
7281 gfx::Size outer_viewport
= gfx::Size(50, 80);
7282 gfx::Size inner_viewport
= gfx::Size(25, 40);
7284 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7286 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7287 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7290 gfx::Vector2dF inner_expected
;
7291 gfx::Vector2dF outer_expected
;
7292 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7293 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7295 // Make sure the scroll goes to the outer viewport first.
7296 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7297 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7298 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7299 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7300 InputHandler::GESTURE
));
7302 // Scroll near the edge of the outer viewport.
7303 gfx::Vector2d
scroll_delta(inner_viewport
.width(), inner_viewport
.height());
7304 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7305 outer_expected
+= scroll_delta
;
7306 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7307 InputHandler::GESTURE
));
7309 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7310 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7312 // Now diagonal scroll across the outer viewport boundary in a single event.
7313 // The entirety of the scroll should be consumed, as bubbling between inner
7314 // and outer viewport layers is perfect.
7315 host_impl_
->ScrollBy(gfx::Point(), gfx::ScaleVector2d(scroll_delta
, 2));
7316 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7317 InputHandler::GESTURE
));
7318 outer_expected
+= scroll_delta
;
7319 inner_expected
+= scroll_delta
;
7320 host_impl_
->ScrollEnd();
7321 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7322 gfx::Point(), InputHandler::GESTURE
));
7324 EXPECT_VECTOR_EQ(inner_expected
, inner_scroll
->CurrentScrollOffset());
7325 EXPECT_VECTOR_EQ(outer_expected
, outer_scroll
->CurrentScrollOffset());
7329 TEST_F(LayerTreeHostImplVirtualViewportTest
,
7330 TouchFlingCanLockToViewportLayerAfterBubbling
) {
7331 gfx::Size content_size
= gfx::Size(100, 160);
7332 gfx::Size outer_viewport
= gfx::Size(50, 80);
7333 gfx::Size inner_viewport
= gfx::Size(25, 40);
7335 SetupVirtualViewportLayers(content_size
, outer_viewport
, inner_viewport
);
7337 LayerImpl
* outer_scroll
= host_impl_
->OuterViewportScrollLayer();
7338 LayerImpl
* inner_scroll
= host_impl_
->InnerViewportScrollLayer();
7340 scoped_ptr
<LayerImpl
> child
=
7341 CreateScrollableLayer(10, outer_viewport
, outer_scroll
);
7342 LayerImpl
* child_scroll
= child
.get();
7343 outer_scroll
->children()[0]->AddChild(child
.Pass());
7347 scoped_ptr
<ScrollAndScaleSet
> scroll_info
;
7349 gfx::Vector2d
scroll_delta(0, inner_viewport
.height());
7350 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7351 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
));
7352 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7353 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7354 InputHandler::GESTURE
));
7356 // The child should have scrolled up to its limit.
7357 scroll_info
= host_impl_
->ProcessScrollDeltas();
7358 ASSERT_EQ(1u, scroll_info
->scrolls
.size());
7359 ExpectContains(*scroll_info
, child_scroll
->id(), scroll_delta
);
7360 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), child_scroll
);
7362 // The first |ScrollBy| after the fling should re-lock the scrolling
7363 // layer to the first layer that scrolled, the inner viewport scroll layer.
7364 EXPECT_EQ(InputHandler::SCROLL_STARTED
, host_impl_
->FlingScrollBegin());
7365 EXPECT_TRUE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7366 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7367 EXPECT_TRUE(host_impl_
->IsCurrentlyScrollingLayerAt(gfx::Point(),
7368 InputHandler::GESTURE
));
7370 // The inner viewport should have scrolled up to its limit.
7371 scroll_info
= host_impl_
->ProcessScrollDeltas();
7372 ASSERT_EQ(2u, scroll_info
->scrolls
.size());
7373 ExpectContains(*scroll_info
, child_scroll
->id(), scroll_delta
);
7374 ExpectContains(*scroll_info
, inner_scroll
->id(), scroll_delta
);
7376 // As the locked layer is at its limit, no further scrolling can occur.
7377 EXPECT_FALSE(host_impl_
->ScrollBy(gfx::Point(), scroll_delta
).did_scroll
);
7378 EXPECT_EQ(host_impl_
->CurrentlyScrollingLayer(), inner_scroll
);
7379 host_impl_
->ScrollEnd();
7380 EXPECT_FALSE(host_impl_
->IsCurrentlyScrollingLayerAt(
7381 gfx::Point(), InputHandler::GESTURE
));
7385 class LayerTreeHostImplWithImplicitLimitsTest
: public LayerTreeHostImplTest
{
7387 void SetUp() override
{
7388 LayerTreeSettings settings
= DefaultSettings();
7389 settings
.max_memory_for_prepaint_percentage
= 50;
7390 CreateHostImpl(settings
, CreateOutputSurface());
7394 TEST_F(LayerTreeHostImplWithImplicitLimitsTest
, ImplicitMemoryLimits
) {
7395 // Set up a memory policy and percentages which could cause
7396 // 32-bit integer overflows.
7397 ManagedMemoryPolicy
mem_policy(300 * 1024 * 1024); // 300MB
7399 // Verify implicit limits are calculated correctly with no overflows
7400 host_impl_
->SetMemoryPolicy(mem_policy
);
7401 EXPECT_EQ(host_impl_
->global_tile_state().hard_memory_limit_in_bytes
,
7402 300u * 1024u * 1024u);
7403 EXPECT_EQ(host_impl_
->global_tile_state().soft_memory_limit_in_bytes
,
7404 150u * 1024u * 1024u);
7407 TEST_F(LayerTreeHostImplTest
, ExternalTransformReflectedInNextDraw
) {
7408 const gfx::Size
layer_size(100, 100);
7409 gfx::Transform external_transform
;
7410 const gfx::Rect
external_viewport(layer_size
);
7411 const gfx::Rect
external_clip(layer_size
);
7412 const bool resourceless_software_draw
= false;
7413 LayerImpl
* layer
= SetupScrollAndContentsLayers(layer_size
);
7415 host_impl_
->SetExternalDrawConstraints(external_transform
,
7420 resourceless_software_draw
);
7422 EXPECT_TRANSFORMATION_MATRIX_EQ(
7423 external_transform
, layer
->draw_properties().target_space_transform
);
7425 external_transform
.Translate(20, 20);
7426 host_impl_
->SetExternalDrawConstraints(external_transform
,
7431 resourceless_software_draw
);
7433 EXPECT_TRANSFORMATION_MATRIX_EQ(
7434 external_transform
, layer
->draw_properties().target_space_transform
);
7437 TEST_F(LayerTreeHostImplTest
, ScrollAnimated
) {
7438 SetupScrollAndContentsLayers(gfx::Size(100, 200));
7441 base::TimeTicks start_time
=
7442 base::TimeTicks() + base::TimeDelta::FromMilliseconds(100);
7444 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7445 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7447 LayerImpl
* scrolling_layer
= host_impl_
->CurrentlyScrollingLayer();
7449 host_impl_
->Animate(start_time
);
7450 host_impl_
->UpdateAnimationState(true);
7452 EXPECT_EQ(gfx::ScrollOffset(), scrolling_layer
->CurrentScrollOffset());
7454 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(50));
7455 host_impl_
->UpdateAnimationState(true);
7457 float y
= scrolling_layer
->CurrentScrollOffset().y();
7458 EXPECT_TRUE(y
> 1 && y
< 49);
7461 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7462 host_impl_
->ScrollAnimated(gfx::Point(), gfx::Vector2d(0, 50)));
7464 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(200));
7465 host_impl_
->UpdateAnimationState(true);
7467 y
= scrolling_layer
->CurrentScrollOffset().y();
7468 EXPECT_TRUE(y
> 50 && y
< 100);
7469 EXPECT_EQ(scrolling_layer
, host_impl_
->CurrentlyScrollingLayer());
7471 host_impl_
->Animate(start_time
+ base::TimeDelta::FromMilliseconds(250));
7472 host_impl_
->UpdateAnimationState(true);
7474 EXPECT_VECTOR_EQ(gfx::ScrollOffset(0, 100),
7475 scrolling_layer
->CurrentScrollOffset());
7476 EXPECT_EQ(NULL
, host_impl_
->CurrentlyScrollingLayer());
7479 TEST_F(LayerTreeHostImplTest
, InvalidLayerNotAddedToRasterQueue
) {
7480 host_impl_
->CreatePendingTree();
7482 Region empty_invalidation
;
7483 scoped_refptr
<RasterSource
> pile_with_tiles(
7484 FakePicturePileImpl::CreateFilledPileWithDefaultTileSize(
7485 gfx::Size(10, 10)));
7487 scoped_ptr
<FakePictureLayerImpl
> layer
=
7488 FakePictureLayerImpl::Create(host_impl_
->pending_tree(), 11);
7489 layer
->SetBounds(gfx::Size(10, 10));
7490 layer
->set_gpu_raster_max_texture_size(host_impl_
->device_viewport_size());
7491 layer
->SetDrawsContent(true);
7492 layer
->tilings()->AddTiling(1.0f
, pile_with_tiles
);
7493 layer
->UpdateRasterSource(pile_with_tiles
, &empty_invalidation
, nullptr);
7494 layer
->tilings()->tiling_at(0)->set_resolution(
7495 TileResolution::HIGH_RESOLUTION
);
7496 layer
->tilings()->tiling_at(0)->CreateAllTilesForTesting();
7497 layer
->tilings()->tiling_at(0)->ComputeTilePriorityRects(
7498 gfx::Rect(gfx::Size(10, 10)), 1.f
, 1.0, Occlusion());
7499 host_impl_
->pending_tree()->SetRootLayer(layer
.Pass());
7501 FakePictureLayerImpl
* root_layer
= static_cast<FakePictureLayerImpl
*>(
7502 host_impl_
->pending_tree()->root_layer());
7504 root_layer
->set_has_valid_tile_priorities(true);
7505 scoped_ptr
<RasterTilePriorityQueue
> non_empty_raster_priority_queue_all
=
7506 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7507 RasterTilePriorityQueue::Type::ALL
);
7508 EXPECT_FALSE(non_empty_raster_priority_queue_all
->IsEmpty());
7510 root_layer
->set_has_valid_tile_priorities(false);
7511 scoped_ptr
<RasterTilePriorityQueue
> empty_raster_priority_queue_all
=
7512 host_impl_
->BuildRasterQueue(TreePriority::SAME_PRIORITY_FOR_BOTH_TREES
,
7513 RasterTilePriorityQueue::Type::ALL
);
7514 EXPECT_TRUE(empty_raster_priority_queue_all
->IsEmpty());
7517 TEST_F(LayerTreeHostImplTest
, DidBecomeActive
) {
7518 host_impl_
->CreatePendingTree();
7519 host_impl_
->ActivateSyncTree();
7520 host_impl_
->CreatePendingTree();
7522 LayerTreeImpl
* pending_tree
= host_impl_
->pending_tree();
7524 scoped_ptr
<FakePictureLayerImpl
> pending_layer
=
7525 FakePictureLayerImpl::Create(pending_tree
, 10);
7526 FakePictureLayerImpl
* raw_pending_layer
= pending_layer
.get();
7527 pending_tree
->SetRootLayer(pending_layer
.Pass());
7528 ASSERT_EQ(raw_pending_layer
, pending_tree
->root_layer());
7530 EXPECT_EQ(0u, raw_pending_layer
->did_become_active_call_count());
7531 pending_tree
->DidBecomeActive();
7532 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7534 scoped_ptr
<FakePictureLayerImpl
> mask_layer
=
7535 FakePictureLayerImpl::Create(pending_tree
, 11);
7536 FakePictureLayerImpl
* raw_mask_layer
= mask_layer
.get();
7537 raw_pending_layer
->SetMaskLayer(mask_layer
.Pass());
7538 ASSERT_EQ(raw_mask_layer
, raw_pending_layer
->mask_layer());
7540 EXPECT_EQ(1u, raw_pending_layer
->did_become_active_call_count());
7541 EXPECT_EQ(0u, raw_mask_layer
->did_become_active_call_count());
7542 pending_tree
->DidBecomeActive();
7543 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7544 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7546 scoped_ptr
<FakePictureLayerImpl
> replica_layer
=
7547 FakePictureLayerImpl::Create(pending_tree
, 12);
7548 scoped_ptr
<FakePictureLayerImpl
> replica_mask_layer
=
7549 FakePictureLayerImpl::Create(pending_tree
, 13);
7550 FakePictureLayerImpl
* raw_replica_mask_layer
= replica_mask_layer
.get();
7551 replica_layer
->SetMaskLayer(replica_mask_layer
.Pass());
7552 raw_pending_layer
->SetReplicaLayer(replica_layer
.Pass());
7553 ASSERT_EQ(raw_replica_mask_layer
,
7554 raw_pending_layer
->replica_layer()->mask_layer());
7556 EXPECT_EQ(2u, raw_pending_layer
->did_become_active_call_count());
7557 EXPECT_EQ(1u, raw_mask_layer
->did_become_active_call_count());
7558 EXPECT_EQ(0u, raw_replica_mask_layer
->did_become_active_call_count());
7559 pending_tree
->DidBecomeActive();
7560 EXPECT_EQ(3u, raw_pending_layer
->did_become_active_call_count());
7561 EXPECT_EQ(2u, raw_mask_layer
->did_become_active_call_count());
7562 EXPECT_EQ(1u, raw_replica_mask_layer
->did_become_active_call_count());
7565 TEST_F(LayerTreeHostImplTest
, WheelScrollWithPageScaleFactorOnInnerLayer
) {
7566 LayerImpl
* scroll_layer
= SetupScrollAndContentsLayers(gfx::Size(100, 100));
7567 host_impl_
->SetViewportSize(gfx::Size(50, 50));
7570 EXPECT_EQ(scroll_layer
, host_impl_
->InnerViewportScrollLayer());
7572 float min_page_scale
= 1.f
, max_page_scale
= 4.f
;
7573 float page_scale_factor
= 1.f
;
7575 // The scroll deltas should have the page scale factor applied.
7577 host_impl_
->active_tree()->PushPageScaleFromMainThread(
7578 page_scale_factor
, min_page_scale
, max_page_scale
);
7579 host_impl_
->SetPageScaleOnActiveTree(page_scale_factor
);
7580 scroll_layer
->SetScrollDelta(gfx::Vector2d());
7582 float page_scale_delta
= 2.f
;
7583 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::GESTURE
);
7584 host_impl_
->PinchGestureBegin();
7585 host_impl_
->PinchGestureUpdate(page_scale_delta
, gfx::Point());
7586 host_impl_
->PinchGestureEnd();
7587 host_impl_
->ScrollEnd();
7589 gfx::Vector2dF
scroll_delta(0, 5);
7590 EXPECT_EQ(InputHandler::SCROLL_STARTED
,
7591 host_impl_
->ScrollBegin(gfx::Point(), InputHandler::WHEEL
));
7592 EXPECT_VECTOR_EQ(gfx::Vector2dF(), scroll_layer
->CurrentScrollOffset());
7594 host_impl_
->ScrollBy(gfx::Point(), scroll_delta
);
7595 host_impl_
->ScrollEnd();
7596 EXPECT_VECTOR_EQ(gfx::Vector2dF(0, 2.5),
7597 scroll_layer
->CurrentScrollOffset());
7601 class LayerTreeHostImplCountingLostSurfaces
: public LayerTreeHostImplTest
{
7603 LayerTreeHostImplCountingLostSurfaces() : num_lost_surfaces_(0) {}
7604 void DidLoseOutputSurfaceOnImplThread() override
{ num_lost_surfaces_
++; }
7607 int num_lost_surfaces_
;
7610 TEST_F(LayerTreeHostImplCountingLostSurfaces
, TwiceLostSurface
) {
7611 // Really we just need at least one client notification each time
7612 // we go from having a valid output surface to not having a valid output
7614 EXPECT_EQ(0, num_lost_surfaces_
);
7615 host_impl_
->DidLoseOutputSurface();
7616 EXPECT_EQ(1, num_lost_surfaces_
);
7617 host_impl_
->DidLoseOutputSurface();
7618 EXPECT_LE(1, num_lost_surfaces_
);
7621 TEST_F(LayerTreeHostImplTest
, RemoveUnreferencedRenderPass
) {
7622 LayerTreeHostImpl::FrameData frame
;
7623 frame
.render_passes
.push_back(RenderPass::Create());
7624 RenderPass
* pass3
= frame
.render_passes
.back();
7625 frame
.render_passes
.push_back(RenderPass::Create());
7626 RenderPass
* pass2
= frame
.render_passes
.back();
7627 frame
.render_passes
.push_back(RenderPass::Create());
7628 RenderPass
* pass1
= frame
.render_passes
.back();
7630 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7631 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7632 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7634 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7635 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7636 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7638 // Add a quad to each pass so they aren't empty.
7639 SolidColorDrawQuad
* color_quad
;
7640 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7641 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7642 color_quad
= pass2
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7643 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7644 color_quad
= pass3
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7645 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7647 // pass3 is referenced by pass2.
7648 RenderPassDrawQuad
* rpdq
=
7649 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7650 rpdq
->material
= DrawQuad::RENDER_PASS
;
7651 rpdq
->render_pass_id
= pass3
->id
;
7653 // But pass2 is not referenced by pass1. So pass2 and pass3 should be culled.
7654 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7655 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7656 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7657 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7658 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7659 EXPECT_EQ(1u, frame
.render_passes
.size());
7660 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7663 TEST_F(LayerTreeHostImplTest
, RemoveEmptyRenderPass
) {
7664 LayerTreeHostImpl::FrameData frame
;
7665 frame
.render_passes
.push_back(RenderPass::Create());
7666 RenderPass
* pass3
= frame
.render_passes
.back();
7667 frame
.render_passes
.push_back(RenderPass::Create());
7668 RenderPass
* pass2
= frame
.render_passes
.back();
7669 frame
.render_passes
.push_back(RenderPass::Create());
7670 RenderPass
* pass1
= frame
.render_passes
.back();
7672 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7673 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7674 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7676 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7677 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7678 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7680 // pass1 is not empty, but pass2 and pass3 are.
7681 SolidColorDrawQuad
* color_quad
;
7682 color_quad
= pass1
->CreateAndAppendDrawQuad
<SolidColorDrawQuad
>();
7683 color_quad
->material
= DrawQuad::SOLID_COLOR
;
7685 // pass3 is referenced by pass2.
7686 RenderPassDrawQuad
* rpdq
=
7687 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7688 rpdq
->material
= DrawQuad::RENDER_PASS
;
7689 rpdq
->render_pass_id
= pass3
->id
;
7691 // pass2 is referenced by pass1.
7692 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7693 rpdq
->material
= DrawQuad::RENDER_PASS
;
7694 rpdq
->render_pass_id
= pass2
->id
;
7696 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7697 // should be removed.
7698 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7699 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7700 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7701 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7702 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7703 EXPECT_EQ(1u, frame
.render_passes
.size());
7704 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7705 // The RenderPassDrawQuad should be removed from pass1.
7706 EXPECT_EQ(1u, pass1
->quad_list
.size());
7707 EXPECT_EQ(DrawQuad::SOLID_COLOR
, pass1
->quad_list
.ElementAt(0)->material
);
7710 TEST_F(LayerTreeHostImplTest
, DoNotRemoveEmptyRootRenderPass
) {
7711 LayerTreeHostImpl::FrameData frame
;
7712 frame
.render_passes
.push_back(RenderPass::Create());
7713 RenderPass
* pass3
= frame
.render_passes
.back();
7714 frame
.render_passes
.push_back(RenderPass::Create());
7715 RenderPass
* pass2
= frame
.render_passes
.back();
7716 frame
.render_passes
.push_back(RenderPass::Create());
7717 RenderPass
* pass1
= frame
.render_passes
.back();
7719 pass1
->SetNew(RenderPassId(1, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7720 pass2
->SetNew(RenderPassId(2, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7721 pass3
->SetNew(RenderPassId(3, 0), gfx::Rect(), gfx::Rect(), gfx::Transform());
7723 frame
.render_passes_by_id
[pass1
->id
] = pass1
;
7724 frame
.render_passes_by_id
[pass2
->id
] = pass2
;
7725 frame
.render_passes_by_id
[pass3
->id
] = pass3
;
7727 // pass3 is referenced by pass2.
7728 RenderPassDrawQuad
* rpdq
=
7729 pass2
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7730 rpdq
->material
= DrawQuad::RENDER_PASS
;
7731 rpdq
->render_pass_id
= pass3
->id
;
7733 // pass2 is referenced by pass1.
7734 rpdq
= pass1
->CreateAndAppendDrawQuad
<RenderPassDrawQuad
>();
7735 rpdq
->material
= DrawQuad::RENDER_PASS
;
7736 rpdq
->render_pass_id
= pass2
->id
;
7738 // Since pass3 is empty it should be removed. Then pass2 is empty too, and
7739 // should be removed. Then pass1 is empty too, but it's the root so it should
7741 FakeLayerTreeHostImpl::RemoveRenderPasses(&frame
);
7742 EXPECT_EQ(1u, frame
.render_passes_by_id
.size());
7743 EXPECT_TRUE(frame
.render_passes_by_id
[RenderPassId(1, 0)]);
7744 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(2, 0)]);
7745 EXPECT_FALSE(frame
.render_passes_by_id
[RenderPassId(3, 0)]);
7746 EXPECT_EQ(1u, frame
.render_passes
.size());
7747 EXPECT_EQ(RenderPassId(1, 0), frame
.render_passes
[0]->id
);
7748 // The RenderPassDrawQuad should be removed from pass1.
7749 EXPECT_EQ(0u, pass1
->quad_list
.size());
7752 class FakeVideoFrameController
: public VideoFrameController
{
7754 void OnBeginFrame(const BeginFrameArgs
& args
) override
{
7755 begin_frame_args_
= args
;
7758 const BeginFrameArgs
& begin_frame_args() { return begin_frame_args_
; }
7761 BeginFrameArgs begin_frame_args_
;
7764 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerInsideFrame
) {
7765 host_impl_
->DidFinishImplFrame();
7767 BeginFrameArgs begin_frame_args
=
7768 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7769 FakeVideoFrameController controller
;
7771 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7772 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7773 host_impl_
->AddVideoFrameController(&controller
);
7774 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7775 host_impl_
->DidFinishImplFrame();
7778 TEST_F(LayerTreeHostImplTest
, AddVideoFrameControllerOutsideFrame
) {
7779 host_impl_
->DidFinishImplFrame();
7781 BeginFrameArgs begin_frame_args
=
7782 CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7783 FakeVideoFrameController controller
;
7785 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7786 host_impl_
->DidFinishImplFrame();
7788 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7789 host_impl_
->AddVideoFrameController(&controller
);
7790 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7792 begin_frame_args
= CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE
);
7793 EXPECT_FALSE(controller
.begin_frame_args().IsValid());
7794 host_impl_
->WillBeginImplFrame(begin_frame_args
);
7795 EXPECT_TRUE(controller
.begin_frame_args().IsValid());
7798 TEST_F(LayerTreeHostImplTest
, GpuRasterizationStatusModes
) {
7799 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7801 host_impl_
->SetHasGpuRasterizationTrigger(true);
7802 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
7803 EXPECT_EQ(GpuRasterizationStatus::ON
, host_impl_
->gpu_rasterization_status());
7804 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7806 host_impl_
->SetHasGpuRasterizationTrigger(false);
7807 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
7808 EXPECT_EQ(GpuRasterizationStatus::OFF_VIEWPORT
,
7809 host_impl_
->gpu_rasterization_status());
7810 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7812 host_impl_
->SetHasGpuRasterizationTrigger(true);
7813 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
7814 EXPECT_EQ(GpuRasterizationStatus::OFF_CONTENT
,
7815 host_impl_
->gpu_rasterization_status());
7816 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7817 EXPECT_FALSE(host_impl_
->use_msaa());
7819 scoped_ptr
<TestWebGraphicsContext3D
> context_with_msaa
=
7820 TestWebGraphicsContext3D::Create();
7821 context_with_msaa
->SetMaxSamples(8);
7823 LayerTreeSettings msaaSettings
= GpuRasterizationEnabledSettings();
7824 msaaSettings
.gpu_rasterization_msaa_sample_count
= 4;
7825 EXPECT_TRUE(CreateHostImpl(
7826 msaaSettings
, FakeOutputSurface::Create3d(context_with_msaa
.Pass())));
7827 host_impl_
->SetHasGpuRasterizationTrigger(true);
7828 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
7829 EXPECT_EQ(GpuRasterizationStatus::MSAA_CONTENT
,
7830 host_impl_
->gpu_rasterization_status());
7831 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7832 EXPECT_TRUE(host_impl_
->use_msaa());
7834 LayerTreeSettings settings
= DefaultSettings();
7835 settings
.gpu_rasterization_enabled
= false;
7836 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
7837 host_impl_
->SetHasGpuRasterizationTrigger(true);
7838 host_impl_
->SetContentIsSuitableForGpuRasterization(true);
7839 EXPECT_EQ(GpuRasterizationStatus::OFF_DEVICE
,
7840 host_impl_
->gpu_rasterization_status());
7841 EXPECT_FALSE(host_impl_
->use_gpu_rasterization());
7843 settings
.gpu_rasterization_forced
= true;
7844 EXPECT_TRUE(CreateHostImpl(settings
, FakeOutputSurface::Create3d()));
7846 host_impl_
->SetHasGpuRasterizationTrigger(false);
7847 host_impl_
->SetContentIsSuitableForGpuRasterization(false);
7848 EXPECT_EQ(GpuRasterizationStatus::ON_FORCED
,
7849 host_impl_
->gpu_rasterization_status());
7850 EXPECT_TRUE(host_impl_
->use_gpu_rasterization());
7853 // A mock output surface which lets us detect calls to ForceReclaimResources.
7854 class MockReclaimResourcesOutputSurface
: public FakeOutputSurface
{
7856 static scoped_ptr
<MockReclaimResourcesOutputSurface
> Create3d() {
7857 return make_scoped_ptr(new MockReclaimResourcesOutputSurface(
7858 TestContextProvider::Create(), TestContextProvider::Create(), false));
7861 MOCK_METHOD0(ForceReclaimResources
, void());
7864 MockReclaimResourcesOutputSurface(
7865 scoped_refptr
<ContextProvider
> context_provider
,
7866 scoped_refptr
<ContextProvider
> worker_context_provider
,
7867 bool delegated_rendering
)
7868 : FakeOutputSurface(context_provider
,
7869 worker_context_provider
,
7870 delegated_rendering
) {}
7873 // Display::Draw (and the planned Display Scheduler) currently rely on resources
7874 // being reclaimed to block drawing between BeginCommit / Swap. This test
7875 // ensures that BeginCommit triggers ForceReclaimResources. See
7876 // crbug.com/489515.
7877 TEST_F(LayerTreeHostImplTest
, BeginCommitReclaimsResources
) {
7878 scoped_ptr
<MockReclaimResourcesOutputSurface
> output_surface(
7879 MockReclaimResourcesOutputSurface::Create3d());
7880 // Hold an unowned pointer to the output surface to use for mock expectations.
7881 MockReclaimResourcesOutputSurface
* mock_output_surface
= output_surface
.get();
7883 CreateHostImpl(DefaultSettings(), output_surface
.Pass());
7884 EXPECT_CALL(*mock_output_surface
, ForceReclaimResources()).Times(1);
7885 host_impl_
->BeginCommit();